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

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

   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 TrojitaCore 0.1
import Dekko.Utils 0.2
import Dekko.Models 0.2
import Dekko.Settings 0.2
import "../Components"

MultipleSelectionListView {
    id: root

    //-----------------------------------
    // PROPERTIES
    //-----------------------------------
    //    property alias hasScrollbar: listViewScrollBar.visible
    property var _currentSwipedItem: null
    property var editActions: [selectAllAction, multiReadAction, multiFlagAction, multiDeleteAction]
    property alias messageFilterModel: messageListFilterModel

    //-----------------------------------
    // SIGNALS
    //-----------------------------------
    signal messageSelected(int msgUid)
    signal threadSelected(int msgUid)

    //-----------------------------------
    // SLOTS
    //-----------------------------------
    onSelectionDone: {
        for (var i=0; i < items.count; i++) {
            accountsListModel.removeRow(items.get(i).index)
        }
    }

    function moveMessage(msgUid) {
        if (mboxPicker.pickerOpened) {
            return
        }
        console.log("[MessageListView] [STATUS] Picking mailbox for ", msgUid)
        mboxPicker.pick()
        mboxPicker.uid = msgUid
    }

    onIsInSelectionModeChanged: {
        if (isInSelectionMode) {
            if (_currentSwipedItem) {
                _currentSwipedItem.resetSwipe()
                _currentSwipedItem = null
            }
            messageListPage.activateMultiSelectToolbar()
        }
    }

    onSelectionCanceled: {
        multiFlagAction.selectedUnFlaggedCount = 0;
        multiReadAction.selectedUnReadCount = 0;
    }

    onMovementStarted: {
        internal.wasAtYBeginning = atYBeginning
        internal.initialContentY = contentY
    }

    onContentYChanged: {
        if (dragging) {
            if (internal.wasAtYBeginning && internal.initialContentY - contentY > units.gu(7)) {
                internal.toBeReloaded = true
            }
            else {
                internal.toBeReloaded = false
            }
        }
    }

    onMovementEnded: {
        if (internal.toBeReloaded) {
            internal.resyncMailbox()
            internal.toBeReloaded = false;
        }
    }

    //----------------------------------
    // FUNCTIONS
    //----------------------------------
    function resetSwipe() {
        if (_currentSwipedItem) {
            _currentSwipedItem.resetSwipe()
            _currentSwipedItem = null
        }
    }

    function _updateSwipeState(item) {
        if (item.swipping) {
            return
        }

        if (item.swipeState !== "Normal") {
            if (_currentSwipedItem !== item) {
                if (_currentSwipedItem) {
                    _currentSwipedItem.resetSwipe()
                }
                _currentSwipedItem = item
            }
        } else if (item.swipeState !== "Normal" && _currentSwipedItem === item) {
            _currentSwipedItem = null
        }
    }

    function setFilter(filterRole) {
        messageListFilterModel.filterRole = filterRole;
        messageListFilterModel.invalidate();
    }

    function updateSelectOperations() {
        var unReadCount = 0;
        var unFlaggedCount = 0;
        for (var i = 0; i < messagesListView.selectedItems.count; i++) {
            if (!messagesListView.selectedItems.get(i).model.isMarkedRead) {
                unReadCount ++;
            }
            if (!messagesListView.selectedItems.get(i).model.isMarkedFlagged) {
                unFlaggedCount ++;
            }
        }
        multiFlagAction.selectedUnFlaggedCount = unFlaggedCount;
        multiReadAction.selectedUnReadCount = unReadCount;
    }

    function determineCurrentIndex() {
        if (dekko.currentAccount.msgModel.hasValidIndex) {
            currentIndex = messageListFilterModel.determineCurrentIndex(dekko.currentAccount.msgModel.uid)
        } else {
            currentIndex = -1
            positionViewAtBeginning()
        }
    }

    //----------------------------------
    // OBJECT PROPERTIES
    //----------------------------------
    clip: true
    //    maximumFlickVelocity: height * 6
    //    flickDeceleration: height * 2
    cacheBuffer: units.gu(300)
    //    section.property: dekko.currentAccount.msgListModel.itemsValid ? "fuzzyDate" : ""
    //    section.delegate: SectionDivider {
    //        text: section ? section : ""
    //    }
    footer: Loader {
        width: parent.width
        height: units.gu(10)
        active: messageListFilterModel.count > limitedProxyModel.limit
        sourceComponent: footerComponent
    }

    highlight: convergenceEnabled && dekko.currentAccount.singleThreadModel.hasValidIndex ? highlightBar : null
    highlightFollowsCurrentItem: convergenceEnabled
    highlightMoveDuration: 200

    listModel: limitedProxyModel
    displaced: Transition {
        UbuntuNumberAnimation {
            property: "y"
        }
    }
    remove: Transition {
        ParallelAnimation {
            UbuntuNumberAnimation {
                property: "height"
                to: 0
            }

            UbuntuNumberAnimation {
                properties: "opacity"
                to: 0
            }
            ScriptAction {
                script: {
                    resetSwipe()
                }
            }
        }
    }
    property int selectionIndex: 0
    listDelegate: MessageListDelegate {
        id: delegate
        function select() {
            if (messagesListView.selectItem(delegate)) {
                root.updateSelectOperations();
            }
        }
        function unselect() {
            if (messagesListView.deselectItem(delegate)) {
                root.updateSelectOperations();
            }
        }
        function enableMultiSelect() {
            if (messageListPage.state !== "search") {
                messagesListView.selectionIndex = model.index
                messagesListView.startSelection();
                select();
            }
        }
        anchors {
            left: parent.left
            right: parent.right
        }
        onMarkMessageDeleted: mailboxUtils.markMessageDeleted(
                                  mailboxUtils.deproxifiedIndex(
                                      root.model.modelIndex(
                                          (model.index))),
                                  !model.isMarkedDeleted)
        onMarkMessageFlagged: flaggedAction.trigger()
        //        // Our actions require a network connection to work
        //        // So stop them if no network is available.
        locked: !dekko.currentAccount.imapModel.isNetworkOnline
        selected: messagesListView.isSelected(delegate)
        selectionMode: messagesListView.isInSelectionMode
        isFirst: model.index === 0

        active: ListView.isCurrentItem

        onItemClicked: {
            if (selectionMode) {
                if (selected) {
                    unselect();
                } else {
                    select();
                }
                return;
            }
            if ((mouse.button === Qt.LeftButton) && (mouse.modifiers & Qt.ControlModifier)) {
                enableMultiSelect();
                return;
            } else if (mouse.button === Qt.RightButton) {
                rightClickActions.trigger()
                return;
            }
            currentIndex = index
            threadSelected(messageUid);
        }
        onItemPressAndHold: enableMultiSelect()
        leftSideAction: deleteAction
        rightSideActions:[flagAction, readAction, extrasAction]
    }

    Action {
        id: multiDeleteAction
        iconName: "delete"
        text: qsTr("Delete")
        onTriggered: {
            for (var i = 0; i < messagesListView.selectedItems.count; i++) {
                mailboxUtils.appendToSelectedIndexList(mailboxUtils.deproxifiedIndex(
                                                           root.model.modelIndex(
                                                               messagesListView.selectedItems.get(i).itemsIndex)));

            }
            mailboxUtils.markSelectedMessagesDeleted(true);
            mailboxUtils.clearSelectedMessages(); // Ensure cleared before proceeding
            messagesListView.clearSelection();
        }
    }

    Action {
        id: multiFlagAction

        property int selectedUnFlaggedCount: 0

        iconName: selectedUnFlaggedCount > 0 || messagesListView.selectedItems.count == 0 ? "favorite-selected" : "non-starred"
        text: selectedUnFlaggedCount > 0 || messagesListView.selectedItems.count == 0 ? qsTr("Star") : qsTr("Remove star")
        onTriggered: {
            for (var i = 0; i < messagesListView.selectedItems.count; i++) {
                if (messagesListView.selectedItems.get(i).model.isMarkedFlagged !== selectedUnFlaggedCount > 0) {
                    mailboxUtils.appendToSelectedIndexList(
                                mailboxUtils.deproxifiedIndex(
                                    root.model.modelIndex(messagesListView.selectedItems.get(i).itemsIndex)));
                }
            }
            mailboxUtils.markSelectedMessagesFlagged(selectedUnFlaggedCount > 0);
            mailboxUtils.clearSelectedMessages();
            messagesListView.clearSelection();
        }
    }

    Action {
        id: multiReadAction

        property int selectedUnReadCount: 0

        iconSource: selectedUnReadCount > 0  || messagesListView.selectedItems.count == 0 ? "qrc:///actions/mail-unread.svg" : "qrc:///actions/mail-read.svg"
        text: selectedUnReadCount > 0 || messagesListView.selectedItems.count == 0 ? qsTr("Mark read") : qsTr("Mark unread")
        onTriggered: {
            for (var i = 0; i < messagesListView.selectedItems.count; i++) {
                if (messagesListView.selectedItems.get(i).model.isMarkedRead !== selectedUnReadCount > 0) {
                    mailboxUtils.appendToSelectedIndexList(
                                mailboxUtils.deproxifiedIndex(
                                    root.model.modelIndex(messagesListView.selectedItems.get(i).itemsIndex)));
                }
            }
            mailboxUtils.markSelectedMessagesAsRead(selectedUnReadCount > 0);
            mailboxUtils.clearSelectedMessages();
            messagesListView.clearSelection();
        }
    }

    Action {
        id: selectAllAction
        property bool allSelected: root.selectedItems.count === root.model.count
        iconSource: allSelected ? "qrc:///actions/select-none.svg" : "qrc:///actions/select.svg"
        text: allSelected ? qsTr("Unselect all") : qsTr("Select all")
        onTriggered: {
            if (!allSelected) {
                messagesListView.selectAll();
            } else {
                messagesListView.clearSelection();
            }
            root.updateSelectOperations();
        }
    }

    //-----------------------------------
    // PRIVATE PROPERTIES & FUNCTIONS
    //-----------------------------------
    QtObject {
        id: internal

        property bool wasAtYBeginning: false
        property bool toBeReloaded: false
        property int initialContentY: 0

        function resyncMailbox() {
            dekko.currentAccount.imapModel.resyncMailbox(dekko.currentAccount.msgListModel.currentMailbox());
        }
    }

    //---------------------------------
    // COMPONENTS
    //---------------------------------
    MailboxUtils {
        id: mailboxUtils
        account: dekko.currentAccount
    }

    MailboxPicker {
        id: mboxPicker
        property var uid
        account: dekko.currentAccount
        onMailboxSelected: {
            mailboxUtils.moveMessageToMailbox(dekko.currentAccount.msgListModel.mailboxName, uid, mboxName)
        }
    }

    MessageListFilterModel {
        id: messageListFilterModel
        sourceModel: dekko.currentAccount.threadingModel
        filterMarkedDeleted: GlobalSettings.preferences.hideMarkedDeleted
    }

    LimitProxyModel {
        id: limitedProxyModel
        // TODO: make this configurable
        limit: 50
        model: messageListFilterModel
    }

    // TODO: Move position bindings from the component to the Loader.
    //       Check all uses of 'parent' inside the root element of the component.
    Component {
        id: footerComponent
        ListItem {
            anchors.fill: parent
            Label {
                anchors.centerIn: parent
                text: qsTr("Load more messages....")
            }
            onClicked: limitedProxyModel.limit = limitedProxyModel.limit + 50
        }
    }

    Component {
        id: highlightBar
        Rectangle {
            color: Qt.rgba(0, 0, 0, 0.05)
        }
    }

    // Update current index if:
    // * Rows removed/inserted
    // * Data changed as we may still be waiting on an inserted row's uid
    //    Connections {
    //        target: messageListFilterModel
    //        onRowsChanged: determineCurrentIndex()
    //        onDataChanged: determineCurrentIndex()
    //    }

    // Update current index when switching accounts
    Connections {
        target: dekko
        onCurrentAccountChanged: {
            if (convergenceEnabled) {
                determineCurrentIndex()
            }
        }
    }

    Connections {
        target: dekko.currentAccount.msgModel
        onHasValidIndexChanged: {
            // This could be down to either the model was hard reset after a reconnect
            // Or we are in a smallFF view and we unset this message so we drop the
            // highlight on small screens.
            if (!dekko.currentAccount.msgModel.hasValidIndex) {
                currentIndex = -1
            }
        }
    }

    Label {
        anchors { left: parent.left; right: parent.right; bottom: parent.top }
        anchors.bottomMargin: root.contentY - root.originY
        height: units.gu(3)
        fontSize: 'medium'
        horizontalAlignment: Text.AlignHCenter
        text: internal.toBeReloaded ? qsTr("Release to refresh...") : qsTr("Pull to refresh...")
    }
}
