/* Copyright (C) 2014-2016 Dan Chapman <dpniel@ubuntu.com>

   This file is part of Dekko email client for Ubuntu Touch/

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License or (at your option) version 3

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.4
import Ubuntu.Components 1.3
import Ubuntu.Components.Popups 1.0
import Ubuntu.Components.ListItems 1.0 as ListItems
import Ubuntu.PushNotifications 0.1
import Dekko.Accounts 0.2
import Dekko.Composition 0.2
import Dekko.Settings 0.2
import Dekko.Theme 0.2
import TrojitaCore 0.1
import Ubuntu.Content 1.0
import "./AccountsView"
import "./Dialogs"
import "./MailboxView"
import "./MessageListView"
import "./Utils"
import "./Contact"
import "./Notifications"
import "./DeveloperMode"
import "./Components"

Item {
    id: dekko

    signal startService()
    signal stopService()

    //-----------------------------------
    // PROPERTIES
    //-----------------------------------
    // This property holds the currently selected account
    // and should be used throughout all other views
    // e.g For a listview set the model to dekko.currentAccount.imapModel
    property alias currentAccount: accountsManager.currentAccount
    property bool msgListPushed: false

    property var mailboxListPage;
    // So we can access it further into the rootPageStack
    property alias accountsManager: accountsManager

    property bool networkAvailable: dekko.currentAccount.imapModel.isNetworkAvailable
    property var submissionManager;

    property var addressbookModel: addressbookModelsLoader.item.addressbookModel
    property var addressbookModelFiltered: addressbookModelsLoader.item.addressbookModelFiltered
    property var recentContactModel: addressbookModelsLoader.item.recentContactModel
    property var recentContactModelFiltered: addressbookModelsLoader.item.recentContactModelFiltered
    property var combinedFlattenContactFilterModel: addressbookModelsLoader.item.combinedFlattenContactFilterModel
    property var flattenContactModel: addressbookModelsLoader.item.flattenContactModel
    property var flattenRecentContactModel: addressbookModelsLoader.item.flattenRecentContactModel
    property var combinedFlattenContactModel: addressbookModelsLoader.item.combinedFlattenContactModel
    property var imapLogDrawer: imapLogDrawerLoader.item
    property alias viewState: view
    property bool setupWizardRunning: false


    //-----------------------------------
    // SIGNALS
    //-----------------------------------
    signal reconnectAttemptScheduled(int timeout)
    signal showAccounts()
    signal autoConfigComplete(var config, string username, string password)
    signal manualConfig(string username, string password)

    //----------------------------------
    // SLOTS
    //----------------------------------
    onReconnectAttemptScheduled: console.log("Reconnect in: " + timeout)

    //----------------------------------
    // OBJECT PROPERTIES
    //----------------------------------
    objectName: "dekko" // object name for functional testing
//    applicationName: "dekko.dekkoproject"
//    automaticOrientation: false
//    anchorToKeyboard: true // ensure page doesn't end up behind the OSK
    // Random values to simulate a phone sized window on desktop
    // THis get's overriden on device
    width: units.gu(120); height: units.gu(80)

    Rectangle {
        anchors.fill: parent
        color: Style.common.background
    }

    //--------------------------------
    // FUNCTIONS
    //--------------------------------
    function setAuthHasFailed(failed) {
        console.log("[setAuthHasFailed] updating alert queue with: authenticateHasFailed =", failed)
        alertQueue.authenticateHasFailed = false
    }

    function openSettings(viewToReturnTo) {
        console.log("[openSettings] Opening settings UI.")
        rootPageStack.clear()
        rootPageStack.push(Qt.resolvedUrl("./Settings/global/GlobalSettingsListView.qml"), {previousView: viewToReturnTo})
    }

    function openMailTo(url) {
        console.log("[openMailTo] Opening mailto: ", url)
        rootPageStack.push(Qt.resolvedUrl("./Composer/ComposePage.qml"),
                       {
                           replyMode: ReplyMode.REPLY_NONE,
                           pageTitle:qsTr("New Message"),
                           mailToUrl: url,
                           isBottomEdgeMode: false
                       });
    }
    property var importTransfer: null
    function handleContentHubImport() {
        if (importTransfer == null) return;
        console.log("[handleContentHubImport] [STATUS] Pushing Compose page....")
       // first get the composer opened and ready
        var composePage = rootPageStack.push(Qt.resolvedUrl("./Composer/ComposePage.qml"),
                                         {
                                             replyMode: ReplyMode.REPLY_NONE,
                                             pageTitle:qsTr("New Message"),
                                             isBottomEdgeMode: false
                                         });
        // Now check iterate over items & add based on ContentType
        console.log("[handleContentHubImport] [INFO] Number of items to add to composer: ", importTransfer.items.length)
        for (var i in importTransfer.items) {
            var url = importTransfer.items[i].url;
            var text = importTransfer.items[i].text;
            console.log("[handleContentHubImport] [INFO] ItemText: ", text)
            console.log("[handleContentHubImport] [INFO] ItemUrl: ", url)
            switch (importTransfer.contentType) {
            case ContentType.Links:
                console.log("[handleContentHubImport] [INFO] ContentType is Link: ", url.toString())
                console.log("[handleContentHubImport] [STATUS] Appending to text body")
                composePage.appendTextToBody(url.toString())
                break
            case ContentType.Text:
                console.log("[handleContentHubImport] [INFO] ContentType is Text: ", url.toString())
                console.log("[handleContentHubImport] [STATUS] Appending to text body")
                composePage.appendTextToBody(text)
                break;
            default:
                console.log("[handleContentHubImport] [INFO] ContentType is Other, most likely a file url: ", url.toString())
                console.log("[handleContentHubImport] [STATUS] Appending to attachments model")
                composePage.addAttachment(url)
                break;
            }
        }
        importTransfer = null
        console.log("[handleContentHubImport] [STATUS] Complete")
    }
    function shareImportAttachments(files) {
        console.log("[shareImportAttachments] [STATUS] Received content hub share...")
        console.log("[shareImportAttachments] [STATUS] Pushing compose page...")
        var composePage = rootPageStack.push(Qt.resolvedUrl("./Composer/ComposePage.qml"),
                                         {
                                             replyMode: ReplyMode.REPLY_NONE,
                                             pageTitle:qsTr("New Message"),
                                             isBottomEdgeMode: false
                                         });
        console.log("[shareImportAttachments] [STATUS] Adding attachments. URLS: ", files)
        composePage.addAttachments(files);
    }



    //--------------------------------
    // ACTIONS
    //--------------------------------

    //--------------------------------
    // PRIVATE PROPERTIES & FUNCTIONS
    //--------------------------------
    ViewState {
        id: view
        anchors.fill: parent
        onStateChanged: console.log("[ViewState::stateChanged] [STATUS] view state is now: ", state)
    }

    AccountsManager {
        id: accountsManager
        onImapError: {
            console.log("[AccountsManager::onAlertReceived] [ERROR] IMAP error with message: ", error.error)
            alertQueue.showImapError(error)
        }
        // FIXME: we are to display a non invasive inline status for this that doesn't prevent app
        // interaction
        // see: https://docs.google.com/a/canonical.com/presentation/d/1woHjO8K4iqyVZZlfQ4BXL0DhYbwkEmZ7wvcUhYzHDRk/edit#slide=id.g183c60488_08 for example
        //        onNetworkError: alertQueue.showNetworkError(error)
        onAlertReceived: {
            console.log("[AccountsManager::onAlertReceived] [ALERT] IMAP alert recieved with message: ", message.message)
            console.debug()
            alertQueue.showImapAlert(message)
        }
        onAuthRequested: {
            console.log("[AccountsManager::onAuthRequested] [STATUS] authentication requested, queuing password job")
            alertQueue.authenticateRequested = true
            passwordManager.requestPassword(account.accountId, PasswordManager.IMAP)
        }
        //        onConnectionStateChanged: console.log("STATE CHANGED")
        onAuthAttemptFailed: {
            console.log("[AccountsManager::onAuthAttemptFailed] [ERROR] Authentication Failed! :-( ")
            console.log("[AccountsManager::onAuthAttemptFailed] [ERROR] Account: ", account.accountId)
            console.log("[AccountsManager::onAuthAttemptFailed] [ERROR] AuthError: ", account.authError)
            alertQueue.authAttemptFailed(account)
        }
        onCheckSslPolicy: {
            console.log("CHECK SSL INFO CALLED")
            alertQueue.showSslInfo(sslInfo)
        }
        onError: console.log("[AccountsManager::error] [ERROR] ", msg)
        onCurrentAccountChanged: {
            if (currentAccount !== null) {
                console.log("Current Account Changed \o/ The id is: " + currentAccount.accountId)
            } else {
                console.log("[WARNING] Unloaded current account.... the next account that opens a connection \
                            is going to steal the msglistview. Be sure this is what you want!!")
            }
        }
        onNoAccountsConfigured: {
            console.log("[AccountsManager::onNoAccountsConfigured] Running setup wizard.")
            rootPageStack.push(Qt.resolvedUrl("./SetupWizard/SetupWizard.qml"), {hasAccounts: false})
            setupWizardRunning = true;
        }

        onNewOnlineAccountCreated: {
            console.log("[AccountsManager::onNewOnlineAccountCreated] NotImplementedYet")
        }
        onNewOnlineAccountEnabled: {
            console.log("[AccountsManager::onNewOnlineAccountEnabled] Checking if SetupWizard is already running")
            if (!setupWizardRunning) {
                console.log("[AccountsManager::onNewOnlineAccountEnabled] SetupWizard not running. Launching now...")
                rootPageStack.push(Qt.resolvedUrl("./SetupWizard/SetupWizard.qml"), {accountType: NewAccountType.ONLINE_ACCOUNT, oaId: id})
                setupWizardRunning = true;
            } else if (setupWizardRunning && count === 0) {
                console.log("[AccountsManager::onNewOnlineAccountEnabled] SetupWizard is alread running, reloading to NewAccountType::ONLINE_ACCOUNT state")
                rootPageStack.pop()
                rootPageStack.push(Qt.resolvedUrl("./SetupWizard/SetupWizard.qml"), {accountType: NewAccountType.ONLINE_ACCOUNT, oaId: id})
            }
        }

        Component.onCompleted: {
            console.log("[AccountsManager::onCompleted] Opening accounts")
            accountsManager.run()
            console.log("[AccountsManager::onCompleted] Setting accounts manager on QNAM factory")
            msgPartNetAccessManagerFactory.setAccountsManager(accountsManager)
        }
    }

    PasswordManager {
        id: passwordManager
        accountsManager: accountsManager
        onPasswordNowAvailable: {
            console.log("[PasswordManager::onPasswordNowAvailable] [STATUS] Password now available for: " + passwordObject.accountId)
            alertQueue.passwordAvailable(passwordObject)
        }
        onAccountUsesOnlineAccounts: {
            console.log("[PasswordManager::onAccountUsesOnlineAccounts] [STATUS] Uses online accounts. Request token for: " + accountObject.accountId)
            alertQueue.accountUsesUOA(accountObject)
        }
        onError: console.log("[PasswordManager::onError] [ERROR]: ", message)
        onReadingFailed: console.log("[PasswordManager::onReadingFailed] [ERROR] Reading failed with message", message)
        onWritingFailed: console.log("[PasswordManager::onWritingFailed] [ERROR] Writing failed with message: ", message)
        onJobCountChanged: console.log("[PasswordManager::jobCountChanged] [STATUS] Number of running password jobs: " + jobsInProgress)
        onPasswordStored: console.log("[PasswordManager::onPasswordStored] [STATUS] Password stored for accountId: " + id)
    }

    QueuedApplicationAlertManager {
        id: alertQueue
        accountsManager: dekko.accountsManager
    }

    Loader {
        id: notificationService
        asynchronous: true
        source: Qt.resolvedUrl("./Notifications/NotificationsService.qml")
    }

    // TODO: Change this as sheets are going to be deprecated
    Component{
        id: sslSheetPage
        SslSheet {
            id: sslSheet
            property string accountId
            onConfirmClicked: accountsManager.setSslPolicy(accountId, true)
            onCancelClicked: accountsManager.setSslPolicy(accountId, false)
        }
    }
    Loader {
        id: addressbookModelsLoader
        asynchronous: true
        source: Qt.resolvedUrl("./Contact/AddressbookModels.qml")
    }

    Connections {
        target: ContentHub
        onImportRequested: {
            console.log("[ContentHub::importRequested] [STATUS] import requested, running import...")
            importTransfer = transfer;
            handleContentHubImport()
        }
        onShareRequested: {
            console.log("[ContentHub::shareRequested] [STATUS] share requested. importing share")
            importTransfer = transfer;
            handleContentHubImport()
        }
        onExportRequested: {
            console.log("ContentHub::exportRequested: NotImplementedYet")
        }
    }

    property var uri: undefined

    Connections {
        target: UriHandler
        onOpened: {
            dekko.uri = uris[0];
            console.log("[UriHandler::opened] [INFO] uri opened: " + dekko.uri);
            processUri();
        }
    }

    function processUri() {
        if (typeof dekko.uri === "undefined") {
            return;
        }

        var mailto = dekko.uri.split(":")[0];
        if (mailto === "mailto") {
            console.log("OPENING MAILTO: ", dekko.uri)
            openMailTo(dekko.uri)
            return
        }
        var commands = dekko.uri.split("://")[1].split("/")
        if (commands) {
            switch(commands[0].toLowerCase()) {
            case "notify":
                console.log("notify received")
                rootPageStack.clear()
                accountsManager.openMailbox(commands[1], commands[2]);
                rootPageStack.push(Qt.resolvedUrl("./MessageListView/MessageListPage.qml"))
                break;
            }
        }
    }

    Component.onCompleted: {
        if (appUris) {
            console.log("WE HAVE A URIs: ", appUris)
            dekko.uri = appUris.substr(1, appUris.length - 2)
            console.log("DEKKO URI: ", dekko.uri)
            processUri()
        }
        if (mailToArgs) {
            console.log("MailToArgs:", mailToArgs)
            dekko.uri = mailToArgs[0]
            if (dekko.uri) {
                processUri()
            }
        }
    }


    Item {
        id: stackWrapper
        anchors {
            left: parent.left
            top: parent.top
            right: parent.right
            bottom: kbdRect.top
        }
        PageStack{
            id:rootPageStack
            onDepthChanged: console.log("[PAGESTACK] depth = " + depth)
            Component.onCompleted: {
                rootPageStack.push(Qt.resolvedUrl("./Stages/MainStage.qml"))
            }
        }


    }

    Loader {
        id: imapLogDrawerLoader
        width: parent.width
        anchors.bottom: parent.bottom
//        height: parent.height
        asynchronous: true
        source: Qt.resolvedUrl("./DeveloperMode/ImapLogDrawer.qml")
        active: GlobalSettings.developer.enableImapModelLogging && GlobalSettings.developer.developerModeEnabled
    }

    KeyboardRectangle {
        id: kbdRect
    }
}
