import QtQuick 2.9
import QtQuick.Dialogs 1.2 // TODO use native dialogs in labs.platform
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.4

import Qt.labs.platform 1.0

import "logic.js" as Logic

ApplicationWindow {
    id: app
    visible: false
    width: 300
    height: 600
    maximumWidth: 300
    minimumWidth: 300
    maximumHeight: 500
    minimumHeight: 300

    property var ctx
    property var loginDone
    property var allowEmptyPass
    property var needsRestart
    property var needsDonate
    property var shownDonate

    onSceneGraphError: function(error, msg) {
        console.debug("ERROR while initializing scene")
        console.debug(msg)
    }

    MainBar {
        id: bar
    }

    StackLayout {

        anchors.fill: parent
        currentIndex: bar.currentIndex

        Item {

            id: infoTab
            anchors.centerIn: parent

            BackgroundImage {
                id: background
            }

            Item {
                id: connBox
                anchors.centerIn: parent

                width: 300
                height: 300

                Rectangle {
                    anchors.fill: parent
                    color: "white"
                    opacity: 0.3
                    layer.enabled: true
                }

                Column {

                    anchors.centerIn: parent
                    spacing: 5

                    Text {
                        id: mainStatus
                        text: "off"
                        font.pixelSize: 26
                        anchors.horizontalCenter: parent.horizontalCenter
                    }

                    Text {
                        id: mainCurrentGateway
                        text: ""
                        font.pixelSize: 20
                        anchors.horizontalCenter: parent.horizontalCenter
                    }

                    VPNSwitch {
                        id: vpntoggle

                        Connections {
                            function onCheckedChanged() {
                                if (vpntoggle.checked == true
                                        && ctx.status == "off") {
                                    backend.switchOn()
                                    vpntoggle.checkable = false
                                }
                                if (vpntoggle.checked === false
                                        && ctx.status == "on") {
                                    backend.switchOff()
                                    vpntoggle.checkable = false
                                }
                            }
                        }
                    }

                    LocationText {
                        id: manualOverrideWarning
                        visible: isManualLocation()
                    }
                } // end column
            } // end inner item
        } // end outer item

        Item {

            id: gatewayTab
            anchors.centerIn: parent

            Column {

                anchors.centerIn: parent
                spacing: 10
                //width: parent.width

                RadioButton {
                    id: autoSelectionButton
                    checked: !isManualLocation()
                    text: qsTr("Recommended")
                    onClicked: {
                        backend.useAutomaticGateway()
                        manualSelectionItem.checked = false
                    }
                }

                RadioButton {
                    id: manualSelectionButton
                    checked: isManualLocation()
                    text: qsTr("Manual")
                    onClicked: setGwSelection()
                }

                ComboBox {
                    id: gwSelector
                    editable: false
                    visible: manualSelectionButton.checked
                    anchors.horizontalCenter: parent.horizontalCenter

                    model: [qsTr("Recommended")]
                    onActivated: {
                        console.debug("Selected gateway:", currentText)
                        if (ctx.status == "off") {
                            gwNextConnectionText.visible = true
                        }
                        if (ctx.status == "on") {
                            gwReconnectText.visible = true
                        }
                        backend.useLocation(currentText.toString())
                        manualSelectionItem.checked = true
                    }

                    delegate: ItemDelegate {
                        // TODO: we could use icons
                        // https://doc.qt.io/qt-5/qml-qtquick-controls2-abstractbutton.html#icon-prop
                        background: Rectangle {
                            color: {
                                "#ffffff"
                                // FIXME locations is not defined when we launch
                                /*
                                const fullness = ctx.locations[modelData]
                                if (fullness >= 0 && fullness < 0.4) {
                                    "#83fc5a"
                                } else if (fullness >= 0.4 && fullness < 0.75) {
                                    "#fcb149"
                                } else if (fullness >= 0.75) {
                                    "#fc5a5d"
                                } else {
                                    "#ffffff"
                                }
                                */
                            }
                        }
                        contentItem: Text {
                            text: modelData
                            font: gwSelector.font
                            color: "#000000"
                        }
                    }

                }

                Text {
                    id: gwReconnectText
                    anchors.horizontalCenter: parent.horizontalCenter
                    width: 180
                    font.pixelSize: 12
                    color: "green"
                    wrapMode: Text.WordWrap 
                    text: qsTr("Reconnecting to the selected gateway…")
                    visible: false
                }

                Text {
                    id: gwNextConnectionText
                    anchors.horizontalCenter: parent.horizontalCenter
                    width: 180
                    font.pixelSize: 12
                    color: "green"
                    wrapMode: Text.WordWrap 
                    text: qsTr("This gateway will be used for next connection.")
                    visible: false
                }

            } // end column
        } // end item

        BridgesItem {
            id: bridgesTab
        }

    } // end stacklayout

    Connections {
        target: jsonModel
        function onDataChanged() {
            ctx = JSON.parse(jsonModel.getJson())
            // TODO pass QML_DEBUG variable to be hyper-verbose
            //console.debug(jsonModel.getJson())

            gwSelector.model = Object.keys(ctx.locations)

            if (ctx.donateDialog == 'true') {
                Logic.setNeedsDonate(true);
            }
            if (ctx.loginDialog == 'true') {
                console.debug(jsonModel.getJson())
                console.debug("DEBUG: should display login")
                login.visible = true
            }
            if (ctx.loginOk == 'true') {
                loginOk.visible = true
            }
            if (ctx.errors) {
                login.visible = false
                if (ctx.errors == "nohelpers") {
                    showInitFailure(
                                qsTr("Could not find helpers. Please check your installation"))
                } else if (ctx.errors == "nopolkit") {
                    showInitFailure(qsTr("Could not find polkit agent."))
                } else {
                    showInitFailure()
                }
            }
            if (ctx.donateURL) {
                donateItem.visible = true
            }

            if (ctx.status == "on") {
                gwNextConnectionText.visible = false
                gwReconnectText.visible = false
            }
        }
    }

    function showInitFailure(msg) {
        console.debug("ERRORS:", ctx.errors)
        if (msg == undefined) {
            if (ctx.errors == 'bad_auth_502'
                    || ctx.errors == 'bad_auth_timeout') {
                msg = qsTr("Oops! The authentication service seems down. Please try again later")
                initFailure.title = qsTr("Service Error")
            } else if (ctx.errors == 'bad_auth') {
                if (allowEmptyPass) {
                    // For now, this is a libraryVPN, so we can be explicit about what credentials are here.
                    // Another option to consider is to customize the error strings while vendoring.
                    //: Incorrect library card number
                    msg = qsTr("Please check your Patron ID")
                } else {
                    msg = qsTr("Could not log in with those credentials, please retry")
                }
                initFailure.title = qsTr("Login Error")
            } else {
                //: %1 -> application name
                //: %2 -> error string
                msg = qsTr("Got an error starting %1: %2").arg(ctx.appName).arg(
                            ctx.errors)
            }
        }
        initFailure.text = msg
        initFailure.visible = true
    }

    function isManualLocation() {
        if (!ctx) {
            return false
        }
        return ctx.manualLocation == "true"
    }

    function hasMultipleGateways() {
        // could also count the gateways
        let provider = Logic.getSelectedProvider(providers);
        if (provider == "riseup") {
            return true;
        } else {
            return false;
        }
    }

    function setGwSelection() {
        if (!isManualLocation()) {
            manualSelectionItem.checked = false
            bar.currentIndex = 1
            app.visible = true
            app.show()
            app.raise()
            return
        }
        // last used manual selection
        const location = ctx.currentLocation.toLowerCase()
        const idx = gwSelector.model.indexOf(location)
        gwSelector.currentIndex = idx
        backend.useLocation(location)
    }

    function showMainWindow() {
            bar.currentIndex = 0
            app.visible = true
            app.show()
            app.raise()
    }

    Component.onCompleted: {
        Logic.debugInit()
        loginDone = false
        allowEmptyPass = Logic.shouldAllowEmptyPass(providers)
        needsRestart = false;
        shownDonate = false;

        /* this is a temporary workaround until general GUI revamp for 0.21.8 */
        let provider = Logic.getSelectedProvider(providers);
        if (provider == "calyx") {
            background.color = "#8EA844";
            background.backgroundVisible = false;
            gwSelector.visible = false;
            manualSelectionButton.visible = false;
        }

        if (!systrayAvailable) {
          app.visible = true
          app.raise()
        }
    }


    property var icons: {
        "off": "qrc:/assets/icon/png/white/vpn_off.png",
        "on": "qrc:/assets/icon/png/white/vpn_on.png",
        "wait": "qrc:/assets/icon/png/white/vpn_wait_0.png",
        "blocked": "qrc:/assets/icon/png/white/vpn_blocked.png"
    }

    VpnState {
        id: vpn
    }

    SystemTrayIcon {

        id: systray
        visible: systrayVisible

        /* the systray menu cannot be buried in a child qml file because
         * otherwise the ids are not available
         * from other components
         */
        menu: Menu {

            id: systrayMenu

            MenuItem {
                id: statusItem
                text: qsTr("Checking status…")
                enabled: false
            }

            MenuSeparator {}

            MenuItem {
                id: autoSelectionItem
                text: qsTr("Recommended")
                checkable: true
                checked: !isManualLocation()
                onTriggered: {
                    backend.useAutomaticGateway()
                    manualSelectionItem.checked = false
                }
            }

            /* a minimal segfault for submenu */
            // Menu {}
            MenuItem {
                id: manualSelectionItem
                text: {
                    if (isManualLocation() != "") {
                        locationStr()
                    } else {
                        qsTr("Pick location…")
                    }
                }
                checkable: true
                checked: isManualLocation()
                onTriggered: setGwSelection()
                visible: hasMultipleGateways()
            }

            MenuItem {
                text: qsTr("Preferences…")
                visible: !hasMultipleGateways()
                onTriggered: showMainWindow()
            }

            MenuSeparator {}

            MenuItem {
                text: {
                    if (vpn.state == "failed")
                        qsTr("Reconnect")
                    else
                        qsTr("Turn on")
                }
                onTriggered: {
                    backend.switchOn()
                }
                visible: ctx ? (ctx.status == "off"
                                || ctx.status == "failed") : false
            }

            MenuItem {
                text: {
                    if (ctx && ctx.status == "starting")
                        qsTr("Cancel")
                    else
                        qsTr("Turn off")
                }
                onTriggered: {
                    backend.switchOff()
                }
                visible: ctx ? (ctx.status == "on" || ctx.status == "starting"
                                || ctx.status == "failed") : false
            }

            MenuSeparator {}

            MenuItem {
                text: qsTr("About…")
                onTriggered: {
                    about.visible = true
                    requestActivate()
                }
            }

            MenuItem {
                id: donateItem
                text: qsTr("Donate…")
                visible: ctx ? ctx.donateURL : false
                onTriggered: {
                    donate.visible = true
                }
            }

            MenuSeparator {}

            MenuItem {
                text: qsTr("Help…")

                onTriggered: {
                    console.debug(Qt.resolvedUrl(ctx.helpURL))
                    Qt.openUrlExternally(Qt.resolvedUrl(ctx.helpURL))
                }
            }

            MenuItem {
                text: qsTr("Report a bug…")

                onTriggered: {
                    Qt.openUrlExternally(
                                Qt.resolvedUrl(
                                    "https://0xacab.org/leap/bitmask-vpn/issues"))
                }
            }

            MenuSeparator {}

            MenuItem {
                text: qsTr("Quit")
                onTriggered: backend.quit()
            }
        }

        Component.onCompleted: {
            systray.icon.source = icons["off"]
            tooltip = qsTr("Checking status…")
            console.debug("systray init completed")
            if (systrayVisible) {
                console.log("show systray")
                if (Qt.platform.os === "windows") {
                    let appname = ctx ? ctx.appName : "VPN"
                    Logic.showNotification(
                        ctx,
                        appname
                        + " is up and running. Please use system tray icon to control it.")
                }
            }
        }
    }

    DonateDialog {
        id: donate
        visible: false
    }

    AboutDialog {
        id: about
        visible: false
    }

    LoginDialog {
        id: login
        visible: false
    }

    LoginOKDialog {
        id: loginOk
        visible: false
    }

    MessageDialog {
        id: errorStartingVPN
        modality: Qt.NonModal
        title: qsTr("Error starting VPN")
        text: ""
        detailedText: ""
        visible: false
    }

    MessageDialog {
        id: authAgent
        modality: Qt.NonModal
        title: qsTr("Missing authentication agent")
        text: qsTr("Could not find a polkit authentication agent. Please run one and try again.")
        visible: false
    }

    FailDialog {
        id: initFailure
        visible: false
    }

    function locationStr() {
        if (ctx.currentLocation && ctx.currentCountry) {
            return ctx.currentLocation + ", " + ctx.currentCountry
        } else {
            return ""
        }
    }

    function useBridges(value) {
        if (value==true) {
            backend.setTransport("obfs4")
        } else {
            backend.setTransport("openvpn")
        }
    }

    property alias brReconnect:bridgesTab.displayReconnect

}