/**
 * SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
 * SPDX-FileCopyrightText: 2021 Bart De Vries <bart@mogwai.be>
 *
 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
 */

import QtQuick
import QtQuick.Controls as Controls
import QtQuick.Layouts

import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.delegates as Delegates
import org.kde.kirigamiaddons.formcard as FormCard

import org.kde.kasts
import org.kde.kasts.settings

import ".."

Kirigami.ScrollablePage {
    id: root

    leftPadding: 0
    rightPadding: 0

    ColumnLayout {
        spacing: 0

        FormCard.FormCard {
            Layout.fillWidth: true

            FormCard.FormTextDelegate {
                id: accountStatus
                text: i18nc("@label", "Account")
                description: Sync.syncEnabled ? i18nc("@info:status Shows which sync account and sync server the user is logged into", "Logged into account \"%1\" on server \"%2\"", Sync.username, (Sync.provider == SyncUtils.GPodderNet && Sync.hostname == "") ? "gpodder.net" : Sync.hostname) : i18nc("@info:status", "Syncing disabled")

                trailing: Controls.Button {
                    text: Sync.syncEnabled ? i18nc("@action:button", "Logout") : i18nc("@action:button", "Login")
                    onClicked: {
                        Sync.syncEnabled ? Sync.logout() : syncProviderOverlay.open();
                    }
                }
            }

            FormCard.FormDelegateSeparator {}

            FormCard.FormTextDelegate {
                id: manualSync
                text: i18nc("@label", "Manually sync")

                trailing: Controls.Button {
                    text: i18nc("@action:button", "Sync Now")
                    enabled: Sync.syncEnabled
                    onClicked: {
                        syncFeedsAndEpisodes.run();
                    }
                }
            }

            FormCard.FormDelegateSeparator {}

            FormCard.FormTextDelegate {
                id: lastFullSync
                text: i18nc("@info:status", "Last full sync with server")
                description: Sync.lastSuccessfulDownloadSync
            }

            FormCard.FormDelegateSeparator {}

            FormCard.FormTextDelegate {
                id: lastQuickUpload
                text: i18nc("@info:status", "Last quick upload to sync server")
                description: Sync.lastSuccessfulUploadSync
            }
        }

        FormCard.FormHeader {
            title: i18nc("@title Form header for settings related to automatic syncing", "Automatic syncing")
            Layout.fillWidth: true
        }

        FormCard.FormCard {
            Layout.fillWidth: true

            FormCard.FormCheckDelegate {
                enabled: Sync.syncEnabled
                checked: SettingsManager.refreshOnStartup
                text: i18nc("@option:check", "Do full sync on startup")
                onToggled: {
                    SettingsManager.refreshOnStartup = checked;
                    SettingsManager.save();
                }
            }

            FormCard.FormCheckDelegate {
                enabled: Sync.syncEnabled
                checked: SettingsManager.syncWhenUpdatingFeeds
                text: i18nc("@option:check", "Do full sync when fetching podcasts")
                onToggled: {
                    SettingsManager.syncWhenUpdatingFeeds = checked;
                    SettingsManager.save();
                }
            }

            FormCard.FormCheckDelegate {
                enabled: Sync.syncEnabled
                checked: SettingsManager.syncWhenPlayerstateChanges
                text: i18nc("@option:check", "Upload episode play positions on play/pause toggle")
                onToggled: {
                    SettingsManager.syncWhenPlayerstateChanges = checked;
                    SettingsManager.save();
                }
            }
        }

        FormCard.FormHeader {
            title: i18nc("@title Form header for advanced settings related to syncing", "Advanced options")
            Layout.fillWidth: true
        }

        FormCard.FormCard {
            Layout.fillWidth: true

            FormCard.FormTextDelegate {
                id: fetchAllEpisodeStates
                text: i18nc("@label", "Fetch all episode states from server")

                trailing: Controls.Button {
                    text: i18nc("@action:button", "Fetch")
                    enabled: Sync.syncEnabled
                    onClicked: {
                        forceSyncFeedsAndEpisodes.run();
                    }
                }
            }

            FormCard.FormDelegateSeparator {}

            FormCard.FormTextDelegate {
                id: fetchLocalEpisodeStates
                text: i18nc("@label", "Push all local episode states to server")

                trailing: Controls.Button {
                    enabled: Sync.syncEnabled
                    text: i18nc("@action:button", "Push")
                    onClicked: {
                        syncPushAllStatesDialog.open();
                    }
                }
            }
        }
    }

    // This item can be used to trigger an update of all feeds; it will open an
    // overlay with options in case the operation is not allowed by the settings
    ConnectionCheckAction {
        id: syncFeedsAndEpisodes

        function action() {
            Sync.doRegularSync();
        }
    }

    // This item can be used to trigger an update of all feeds; it will open an
    // overlay with options in case the operation is not allowed by the settings
    ConnectionCheckAction {
        id: forceSyncFeedsAndEpisodes

        function action() {
            Sync.doForceSync();
        }
    }

    Kirigami.Dialog {
        id: syncPushAllStatesDialog
        preferredWidth: Kirigami.Units.gridUnit * 25
        padding: Kirigami.Units.largeSpacing

        showCloseButton: true
        standardButtons: Controls.DialogButtonBox.Ok | Controls.DialogButtonBox.Cancel
        closePolicy: Kirigami.Dialog.CloseOnEscape | Kirigami.Dialog.CloseOnPressOutside

        title: i18nc("@label", "Push all local episode states to server?")

        onAccepted: {
            syncPushAllStatesDialog.close();
            syncPushAllStates.run();
        }
        onRejected: syncPushAllStatesDialog.close();

        RowLayout {
            spacing: Kirigami.Units.largeSpacing
            Kirigami.Icon {
                Layout.preferredHeight: Kirigami.Units.gridUnit * 4
                Layout.preferredWidth: Kirigami.Units.gridUnit * 4
                source: Sync.provider === Sync.GPodderNextcloud ? "kaccounts-nextcloud" : "gpodder"
            }
            TextEdit {
                Layout.fillWidth: true
                Layout.fillHeight: true
                readOnly: true
                wrapMode: Text.WordWrap
                text: i18nc("@label", "Please note that pushing the playback state of all local episodes to the server might take a very long time and/or might overload the server. Also note that this action will overwrite all existing episode states on the server.\n\nContinue?")
                color: Kirigami.Theme.textColor
                Keys.onReturnPressed: accepted();
            }
        }
    }

    // This item can be used to trigger a push of all episode states to the server;
    // it will open an overlay with options in case the operation is not allowed by the settings
    ConnectionCheckAction {
        id: syncPushAllStates

        function action() {
            Sync.doSyncPushAll();
        }
    }

    Kirigami.Dialog {
        id: syncProviderOverlay
        preferredWidth: Kirigami.Units.gridUnit * 20
        standardButtons: Kirigami.Dialog.NoButton

        showCloseButton: true

        title: i18nc("@label", "Select Sync Provider")

        ColumnLayout {
            spacing: 0

            Repeater {
                focus: syncProviderOverlay.visible

                model: ListModel {
                    id: providerModel
                }
                Component.onCompleted: {
                    providerModel.append({"name": i18nc("@label", "gpodder.net"),
                                        "subtitle": i18nc("@label", "Synchronize with official gpodder.net server"),
                                        "icon": "gpodder",
                                        "provider": Sync.GPodderNet});
                    providerModel.append({"name": i18nc("@label", "GPodder Nextcloud"),
                                        "subtitle": i18nc("@label", "Synchronize with GPodder Nextcloud app"),
                                        "icon": "kaccounts-nextcloud",
                                        "provider": Sync.GPodderNextcloud});
                }
                delegate: Delegates.RoundedItemDelegate {
                    id: syncProviderRepeaterDelegate
                    Layout.fillWidth: true
                    text: model.name
                    icon.name: model.icon
                    contentItem: Delegates.SubtitleContentItem {
                        itemDelegate: syncProviderRepeaterDelegate
                        subtitle: model.subtitle
                    }
                    Keys.onReturnPressed: clicked()
                    onClicked: {
                        Sync.provider = model.provider;
                        syncProviderOverlay.close();
                        syncLoginOverlay.open();
                    }
                }
            }
        }
    }

    Kirigami.Dialog {
        id: syncLoginOverlay
        preferredWidth: Kirigami.Units.gridUnit * 25
        padding: Kirigami.Units.largeSpacing

        showCloseButton: true
        standardButtons: Controls.DialogButtonBox.Ok | Controls.DialogButtonBox.Cancel
        closePolicy: Kirigami.Dialog.CloseOnEscape | Kirigami.Dialog.CloseOnPressOutside

        title: i18nc("@title of dialog box", "Sync Login Credentials")

        onAccepted: {
            if (Sync.provider === Sync.GPodderNextcloud || customServerCheckBox.checked) {
                Sync.hostname = hostnameField.text;
            } else {
                Sync.hostname = ""
            }
            Sync.login(usernameField.text, passwordField.text);
            syncLoginOverlay.close();
        }
        onRejected: syncLoginOverlay.close();

        Column {
            spacing: Kirigami.Units.largeSpacing
            RowLayout {
                width: parent.width
                spacing: Kirigami.Units.largeSpacing
                Kirigami.Icon {
                    Layout.preferredHeight: Kirigami.Units.gridUnit * 4
                    Layout.preferredWidth: Kirigami.Units.gridUnit * 4
                    source: Sync.provider === Sync.GPodderNextcloud ? "kaccounts-nextcloud" : "gpodder"
                }
                ColumnLayout {
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    Kirigami.Heading {
                        clip: true
                        level: 2
                        text: Sync.provider === Sync.GPodderNextcloud ? i18nc("@label", "Sync with GPodder Nextcloud app") : i18nc("@label", "Sync with gpodder.net service")
                    }
                    TextEdit {
                        Layout.fillWidth: true
                        readOnly: true
                        wrapMode: Text.WordWrap
                        textFormat: Text.RichText
                        onLinkActivated: (link) => {
                            Qt.openUrlExternally(link);
                        }
                        text: Sync.provider === Sync.GPodderNextcloud ?
                            i18nc("@label argument is a weblink", "Sync with a Nextcloud server that has the GPodder Sync app installed: %1.<br/>It is advised to manually create an app password for Kasts through the web interface and use those credentials." , "<a href=\"https://apps.nextcloud.com/apps/gpoddersync\">https://apps.nextcloud.com/apps/gpoddersync</a>") :
                            i18nc("@label argument is a weblink", "If you don't already have an account, you should first create one at %1", "<a href=\"https://gpodder.net\">https://gpodder.net</a>")
                        color: Kirigami.Theme.textColor
                    }
                }
            }
            GridLayout {
                width: parent.width
                columns: 2
                rowSpacing: Kirigami.Units.smallSpacing
                columnSpacing: Kirigami.Units.smallSpacing
                Controls.Label {
                    Layout.alignment: Qt.AlignRight
                    text: i18nc("@label:textbox", "Username:")
                }
                Controls.TextField {
                    id: usernameField
                    Layout.fillWidth: true
                    text: Sync.username
                    Keys.onReturnPressed: syncLoginOverlay.accepted();
                    // focus: syncLoginOverlay.visible // disabled for now since it causes problem with virtual keyboard appearing at the same time as the overlay
                }
                Controls.Label {
                    Layout.alignment: Qt.AlignRight
                    text: i18nc("@label:textbox", "Password:")
                }
                Controls.TextField {
                    id: passwordField
                    Layout.fillWidth: true
                    echoMode: TextInput.Password
                    text: Sync.password
                    Keys.onReturnPressed: syncLoginOverlay.accepted();
                }
                Controls.CheckBox {
                    id: customServerCheckBox
                    Layout.row: 2
                    Layout.column: 1
                    visible: Sync.provider === Sync.GPodderNet
                    checked: false
                    text: i18nc("@option:check", "Use custom server")
                }
                Controls.Label {
                    visible: Sync.provider === Sync.GPodderNextcloud || customServerCheckBox.checked
                    Layout.alignment: Qt.AlignRight
                    text: i18nc("@label:textbox", "Hostname:")
                }
                Controls.TextField {
                    visible: Sync.provider === Sync.GPodderNextcloud || customServerCheckBox.checked
                    id: hostnameField
                    Layout.fillWidth: true
                    placeholderText: Sync.provider === Sync.GPodderNet ? "https://gpodder.net" : "https://nextcloud.mydomain.org"
                    text: Sync.hostname
                    Keys.onReturnPressed: syncLoginOverlay.accepted();
                }
            }
        }
    }

    Connections {
        target: Sync
        function onDeviceListReceived() {
            syncDeviceOverlay.open();
            syncDeviceOverlay.update();
        }
        function onLoginSucceeded() {
            if (Sync.provider === Sync.GPodderNextcloud) {
                firstSyncOverlay.open();
            }
        }
    }

    Kirigami.Dialog {
        id: syncDeviceOverlay
        preferredWidth: Kirigami.Units.gridUnit * 25
        padding: Kirigami.Units.largeSpacing

        showCloseButton: true

        title: i18nc("@title", "Sync Device Settings")

        Column {
            spacing: Kirigami.Units.largeSpacing * 2
            Kirigami.Heading {
                level: 2
                text: i18nc("@action:button", "Create a new device")
            }
            GridLayout {
                columns: 2
                width: parent.width
                Controls.Label {
                    text: i18nc("@label:textbox", "Device Name:")
                }
                Controls.TextField {
                    id: deviceField
                    Layout.fillWidth: true
                    text: Sync.suggestedDevice
                    Keys.onReturnPressed: createDeviceButton.clicked();
                    // focus: syncDeviceOverlay.visible // disabled for now since it causes problem with virtual keyboard appearing at the same time as the overlay
                }
                Controls.Label {
                    text: i18nc("@label:textbox", "Device Description:")
                }
                Controls.TextField {
                    id: deviceNameField
                    Layout.fillWidth: true
                    text: Sync.suggestedDeviceName
                    Keys.onReturnPressed: createDeviceButton.clicked();
                }
                Controls.Label {
                    text: i18nc("@label:listbox", "Device Type:")
                }
                Controls.ComboBox {
                    id: deviceTypeField
                    textRole: "text"
                    valueRole: "value"
                    popup.z: 102 // popup has to go in front of OverlaySheet
                    model: [{"text": i18nc("@item:inlistbox type of device", "other"), "value": "other"},
                            {"text": i18nc("@item:inlistbox type of device", "desktop"), "value": "desktop"},
                            {"text": i18nc("@item:inlistbox type of device", "laptop"), "value": "laptop"},
                            {"text": i18nc("@item:inlistbox type of device", "server"), "value": "server"},
                            {"text": i18nc("@item:inlistbox type of device", "mobile"), "value": "mobile"}]
                }
            }
            Controls.Button {
                id: createDeviceButton
                text: i18nc("@action:button", "Create Device")
                icon.name: "list-add"
                onClicked: {
                    Sync.registerNewDevice(deviceField.text, deviceNameField.text, deviceTypeField.currentValue);
                    syncDeviceOverlay.close();
                }
            }
            ListView {
                id: deviceList
                width: parent.width
                height: contentItem.childrenRect.height
                visible: deviceListModel.count !== 0

                header: Kirigami.Heading {
                    topPadding: Kirigami.Units.gridUnit
                    bottomPadding: Kirigami.Units.largeSpacing
                    level: 2
                    text: i18nc("@label", "or select an existing device")
                }
                model: ListModel {
                    id: deviceListModel
                }

                delegate: Delegates.RoundedItemDelegate {
                    text: model.device.caption
                    icon.name: model.device.type == "desktop" ? "computer" :
                        model.device.type == "laptop" ? "computer-laptop" :
                        model.device.type == "server" ? "network-server-database" :
                        model.device.type == "mobile" ? "smartphone" :
                        "emblem-music-symbolic"
                    onClicked: {
                        syncDeviceOverlay.close();
                        Sync.device = model.device.id;
                        Sync.deviceName = model.device.caption;
                        Sync.syncEnabled = true;
                        syncGroupOverlay.open();
                    }
                }
            }
        }

        function update() {
            deviceListModel.clear();
            for (var index in Sync.deviceList) {
                deviceListModel.append({"device": Sync.deviceList[index]});
            }
        }
    }

    Connections {
        target: Sync
        function onDeviceCreated() {
            syncGroupOverlay.open();
        }
    }

    Kirigami.Dialog {
        id: syncGroupOverlay
        preferredWidth: Kirigami.Units.gridUnit * 25
        padding: Kirigami.Units.largeSpacing

        showCloseButton: true
        standardButtons: Controls.DialogButtonBox.Ok | Controls.DialogButtonBox.Cancel
        closePolicy: Kirigami.Dialog.CloseOnEscape | Kirigami.Dialog.CloseOnPressOutside

        title: i18nc("@title of dialog box", "Device Sync Settings")

        onAccepted: {
            Sync.linkUpAllDevices();
            syncGroupOverlay.close();
        }
        onRejected: {
            syncGroupOverlay.close();
        }

        RowLayout {
            spacing: Kirigami.Units.largeSpacing
            Kirigami.Icon {
                Layout.preferredHeight: Kirigami.Units.gridUnit * 4
                Layout.preferredWidth: Kirigami.Units.gridUnit * 4
                source: "gpodder"
            }
            TextEdit {
                Layout.fillWidth: true
                Layout.fillHeight: true
                readOnly: true
                wrapMode: Text.WordWrap
                text: i18nc("@label", "Should all podcast subscriptions on this gpodder.net account be synced across all devices?\nIf you don't know what this means, you should probably select \"Ok\".")
                color: Kirigami.Theme.textColor
                Keys.onReturnPressed: accepted();
            }
        }

        onVisibleChanged: {
            if (!visible) {
                firstSyncOverlay.open();
            }
        }
    }

    Kirigami.Dialog {
        id: firstSyncOverlay
        preferredWidth: Kirigami.Units.gridUnit * 16
        padding: Kirigami.Units.largeSpacing

        showCloseButton: true
        standardButtons: Controls.DialogButtonBox.Ok | Controls.DialogButtonBox.Cancel
        closePolicy: Kirigami.Dialog.CloseOnEscape | Kirigami.Dialog.CloseOnPressOutside

        title: i18nc("@title of dialog box", "Sync Now?")

        onAccepted: {
            firstSyncOverlay.close();
            Sync.doRegularSync();
        }
        onRejected: firstSyncOverlay.close();

        RowLayout {
            spacing: Kirigami.Units.largeSpacing
            Kirigami.Icon {
                Layout.preferredHeight: Kirigami.Units.gridUnit * 4
                Layout.preferredWidth: Kirigami.Units.gridUnit * 4
                source: Sync.provider === Sync.GPodderNextcloud ? "kaccounts-nextcloud" : "gpodder"
            }
            TextEdit {
                Layout.fillWidth: true
                Layout.fillHeight: true
                readOnly: true
                wrapMode: Text.WordWrap
                text: i18nc("@label", "Perform a first sync now?")
                color: Kirigami.Theme.textColor
                Keys.onReturnPressed: accepted();
            }
        }
    }
}
