import QtQuick 2.9
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Extras 1.2
import Qt.labs.platform 1.1

ApplicationWindow {

    id: app
    visible: false

    property var ctx
    property var loginDone 
    property var allowEmptyPass

    Connections {
        target: jsonModel
        onDataChanged: {
            ctx = JSON.parse(jsonModel.getJson());

            // FIXME -- we need to inform the backend that we've already seen
            // this. Otherwise this keeps popping randonmly on state changes.
            if (ctx.donateDialog == 'true') {
                console.debug(jsonModel.getJson())
                donate.visible = 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. Check your installation"))
               } else if ( ctx.errors == "nopolkit" ) {
                   showInitFailure(qsTr("Could not find polkit agent."))
               } else {
                   showInitFailure()
               }
            }
        }
    }

    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.
                  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 shouldAllowEmptyPass() {
        let obj = JSON.parse(providers.getJson())
        let active = obj['default']
        let allProviders = obj['providers']
        for (let i = 0; i < allProviders.length; i++) {
            if (allProviders[i]['name'] === active) {
                return (allProviders[i]['authEmptyPass'] === 'true')
            }
        }
        return false
    }

    Component.onCompleted: {
        loginDone = false;

        /* stupid as it sounds, windows doesn't like to have the systray icon
         not being attached to an actual application window.
         We can still use this quirk, and can use the AppWindow with deferred
         Loaders as a placeholder for all the many dialogs, or to load
         a nice splash screen etc...  */

        console.debug("DEBUG: Pre-seeded providers:");
        console.debug(providers.getJson());

        allowEmptyPass = shouldAllowEmptyPass()

        app.visible = true;
        show();
        hide();
    }

    function toHuman(st) {
        switch(st) {
            case "off":
		//: %1 -> application name
                return qsTr("%1 off").arg(ctx.appName);
            case "on":
		//: %1 -> application name
                return qsTr("%1 on").arg(ctx.appName);
            case "connecting":
		//: %1 -> application name
                return qsTr("Connecting to %1").arg(ctx.appName);
            case "stopping":
		//: %1 -> application name
                return qsTr("Stopping %1").arg(ctx.appName);
            case "failed":
		//: %1 -> application name
                return qsTr("%1 blocking internet").arg(ctx.appName); // TODO failed is not handed yet
        }
    }

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

    SystemTrayIcon {

        id: systray
        visible: systrayVisible

        onActivated: {
            // this looks like a widget bug. middle click (reasons 3 or 4)
            // produce a segfault when trying to call menu.open()
            // left and right click seem to be working fine, so let's ignore this for now.
            switch (reason) {
            case SystemTrayIcon.Unknown:
	        console.debug("reason: unknown")
                menu.open()
		break
            case SystemTrayIcon.Context:
	        console.debug("activated: context")
		if (Qt.platform.os !== "linux") {
			menu.open()
		}
                break
            case SystemTrayIcon.DoubleClick:
	        console.debug("activated: double click")
		if (Qt.platform.os !== "linux") {
			menu.open()
		}
                break
            case SystemTrayIcon.Trigger:
                break
            case SystemTrayIcon.MiddleClick:
                break
            }
        }

        Component.onCompleted: {
            icon.source = icons["off"]
            tooltip = qsTr("Checking status...")
            console.debug("systray init completed")
            hide();
            if (systrayVisible) {
                show();
            }
        }

        menu: Menu {

            id: systrayMenu

            StateGroup {
                id: vpn
                state: ctx ? ctx.status : ""
            
                states: [
                    State { name: "initializing" },
                    State {
                        name: "off"
                        PropertyChanges { target: systray; tooltip: toHuman("off"); icon.source: icons["off"] }
                        PropertyChanges { target: statusItem; text: toHuman("off") }
                    },
                    State {
                        name: "on"
                        PropertyChanges { target: systray; tooltip: toHuman("on"); icon.source: icons["on"] }
                        PropertyChanges { target: statusItem; text: toHuman("on") }
                    },
                    State {
                        name: "starting"
                        PropertyChanges { target: systray; tooltip: toHuman("connecting"); icon.source: icons["wait"] }
                        PropertyChanges { target: statusItem; text: toHuman("connecting") }
                    },
                    State {
                        name: "stopping"
                        PropertyChanges { target: systray; tooltip: toHuman("stopping"); icon.source: icons["wait"] }
                        PropertyChanges { target: statusItem; text: toHuman("stopping") }
                    },
                    State {
                        name: "failed"
                        PropertyChanges { target: systray; tooltip: toHuman("failed"); icon.source: icons["blocked"] }
                        PropertyChanges { target: statusItem; text: toHuman("failed") }
                    }
                ]
            }

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

            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("Help...")
                onTriggered: Qt.openUrlExternally(ctx.helpURL)
            }

            MenuItem {
                text: qsTr("Donate...")
                visible: ctx && ctx.donateURL
                onTriggered: { donate.visible = true }
            }

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

            MenuSeparator {}

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

    DonateDialog {
        id: donate
        visible: false
    }

    AboutDialog {
        id: about
        visible: false
    }

    LoginDialog {
        id: login
        visible: false
    }

    LoginOKDialog{
        id: loginOk
        visible: false
    }

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

    MessageDialog {
        id: authAgent
        buttons: MessageDialog.Ok
        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
    }
}