/*
    Copyright 2017 Benjamin Vedder	benjamin@vedder.se

    This file is part of VESC Tool.

    VESC Tool 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 3 of the License, or
    (at your option) any later version.

    VESC Tool 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.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3

import Ennoid.bmsinterface 1.0
import Ennoid.commands 1.0
import Ennoid.configparams 1.0
import Ennoid.fwhelper 1.0
import Ennoid.utility 1.0

Item {
    property Commands mCommands: VescIf.commands()
    property ConfigParams mInfoConf: VescIf.infoConfig()

    FwHelper {
        id: fwHelper
    }

    ColumnLayout {
        anchors.fill: parent
        spacing: 0

        RowLayout {
            Layout.fillHeight: true
            Layout.fillWidth: true
            spacing: 0

            Rectangle {
                color: "#4f4f4f"
                width: 16
                Layout.fillHeight: true
                Layout.alignment: Qt.AlignHCenter |  Qt.AlignVCenter

                PageIndicator {
                    id: indicator
                    count: swipeView.count
                    currentIndex: swipeView.currentIndex

                    Layout.preferredWidth: 15
                    Layout.alignment: Qt.AlignHCenter |  Qt.AlignVCenter
                    rotation: 90
                }
            }
            SwipeView {
                id: swipeView
                enabled: true
                clip: true

                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.rightMargin: 15
                orientation: Qt.Vertical

                Page {
                    ColumnLayout {
                        anchors.fill: parent
                        anchors.leftMargin: 10
                        anchors.rightMargin: 10

                        Rectangle {
                            Layout.fillWidth: true
                            height: 30;
                            border.width: 0
                            gradient: Gradient {
                                GradientStop {
                                    position: 0.00;
                                    color: "#002dcbff";
                                }

                                GradientStop {
                                    position: 0.3;
                                    color: "#80014cb2";
                                }
                                GradientStop {
                                    position: 0.7;
                                    color: "#80014cb2";
                                }

                                GradientStop {
                                    position: 1.00;
                                    color: "#000dc3ff";
                                }

                            }
                            border.color: "#00000000"

                            Text {
                                anchors.centerIn: parent
                                color: "white"
                                text: "Included Files"
                                font.bold: true
                                verticalAlignment: Text.AlignVCenter
                                horizontalAlignment: Text.AlignHCenter
                            }
                        }

                        Item {
                            // Spacer
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                        }

                        Text {
                            color: "white"
                            Layout.fillWidth: true
                            height: 30;
                            text: "Hardware"
                            horizontalAlignment: Text.AlignHCenter
                        }

                        ComboBox {
                            id: hwBox
                            Layout.preferredHeight: 48
                            Layout.fillWidth: true
                            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter

                            textRole: "key"
                            model: ListModel {
                                id: hwItems
                            }

                            Component.onCompleted: {
                                updateHw("")
                            }

                            onCurrentIndexChanged: {
                                if (hwItems.rowCount() === 0) {
                                    return
                                }

                                var fws = fwHelper.getFirmwares(hwItems.get(hwBox.currentIndex).value)

                                fwItems.clear()

                                for (var name in fws) {
                                    if (name.toLowerCase().indexOf("ENNOID-BMS.bin") !== -1) {
                                        fwItems.insert(0, { key: name, value: fws[name] })
                                    } else {
                                        fwItems.append({ key: name, value: fws[name] })
                                    }
                                }

                                fwBox.currentIndex = 0
                            }
                        }

                        Text {
                            color: "white"
                            Layout.fillWidth: true
                            height: 30;
                            text: "Firmware"
                            horizontalAlignment: Text.AlignHCenter
                        }

                        ComboBox {
                            id: fwBox
                            Layout.preferredHeight: 48
                            Layout.fillWidth: true
                            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter

                            textRole: "key"
                            model: ListModel {
                                id: fwItems
                            }
                        }

                        Button {
                            text: "Show Changelog"
                            Layout.fillWidth: true

                            onClicked: {
                                VescIf.emitMessageDialog(
                                            "Firmware Changelog",
                                            Utility.fwChangeLog(),
                                            true)
                            }
                        }

                        Item {
                            // Spacer
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                        }
                    }
                }

                Page {
                    ColumnLayout {
                        anchors.fill: parent
                        anchors.leftMargin: 10
                        anchors.rightMargin: 10

                        Rectangle {
                            Layout.fillWidth: true
                            height: 30;
                            border.width: 0
                            gradient: Gradient {
                                GradientStop {
                                    position: 0.00;
                                    color: "#002dcbff";
                                }
                                GradientStop {
                                    position: 0.3;
                                    color: "#80014cb2";
                                }
                                GradientStop {
                                    position: 0.7;
                                    color: "#80014cb2";
                                }
                                GradientStop {
                                    position: 1;
                                    color: "#000dc3ff";
                                }

                            }
                            border.color: "#00000000"

                            Text {
                                anchors.centerIn: parent
                                color: "white"
                                text: "Custom File"
                                font.bold: true
                                verticalAlignment: Text.AlignVCenter
                                horizontalAlignment: Text.AlignHCenter
                            }
                        }

                        Item {
                            // Spacer
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                        }

                        TextInput {
                            color: "white"
                            id: customFwText
                            Layout.fillWidth: true
                        }

                        Button {
                            text: "Choose File..."
                            Layout.fillWidth: true

                            onClicked: {
                                if (Utility.requestFilePermission()) {
                                    filePicker.enabled = true
                                    filePicker.visible = true
                                } else {
                                    VescIf.emitMessageDialog(
                                                "File Permissions",
                                                "Unable to request file system permission.",
                                                false, false)
                                }
                            }
                        }

                        Item {
                            // Spacer
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                        }
                    }
                        FilePicker {
                            id: filePicker
                            anchors.fill: parent
                            showDotAndDotDot: true
                            nameFilters: "*.bin"
                            visible: false
                            enabled: false

                            onFileSelected: {
                                customFwText.text = currentFolder() + "/" + fileName
                                visible = false
                                enabled = false
                            }
                        }
                    }

                Page {
                    ColumnLayout {
                        anchors.fill: parent
                        anchors.leftMargin: 10
                        anchors.rightMargin: 10

                        Rectangle {
                            Layout.fillWidth: true
                            height: 30;
                            border.width: 0
                            gradient: Gradient {
                                GradientStop {
                                    position: 0.00;
                                    color: "#002dcbff";
                                }

                                GradientStop {
                                    position: 0.3;
                                    color: "#80014cb2";
                                }

                                GradientStop {
                                    position: 0.7;
                                    color: "#80014cb2";
                                }

                                GradientStop {
                                    position: 1.00;
                                    color: "#000dc3ff"
                                }
                            }
                            border.color: "#00000000"

                            Text {
                                anchors.centerIn: parent
                                color: "white"
                                text: "Bootloader"
                                font.bold: true
                                verticalAlignment: Text.AlignVCenter
                                horizontalAlignment: Text.AlignHCenter
                            }
                        }

                        Item {
                            // Spacer
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                        }

                        Text {
                            color: "white"
                            Layout.fillWidth: true
                            height: 30;
                            text: "Hardware"
                            horizontalAlignment: Text.AlignHCenter
                        }

                        ComboBox {
                            id: blBox
                            Layout.preferredHeight: 48
                            Layout.fillWidth: true
                            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter

                            textRole: "key"
                            model: ListModel {
                                id: blItems
                            }

                            Component.onCompleted: {
                                updateBl("")
                            }
                        }

                        Item {
                            // Spacer
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                        }
                    }
                }
            }
        }

        Rectangle {
            Layout.fillWidth: true
            height: asd.implicitHeight + 20
            color: "#414141"

            ColumnLayout {
                id: asd
                anchors.fill: parent
                anchors.margins: 10

                Text {
                    Layout.fillWidth: true
                    color: "white"
                    id: uploadText
                    text: qsTr("Not Uploading")
                    horizontalAlignment: Text.AlignHCenter
                }

                ProgressBar {
                    id: uploadProgress
                    Layout.fillWidth: true
                }

                RowLayout {
                    Layout.fillWidth: true

                    Button {
                        id: uploadButton
                        text: qsTr("Upload")
                        Layout.fillWidth: true

                        onClicked: {
                            if (!VescIf.isPortConnected()) {
                                VescIf.emitMessageDialog(
                                            "Connection Error",
                                            "The BMS is not connected. Please open a connection.",
                                            false)
                                return
                            }

                            if (swipeView.currentIndex == 0) {
                                if (fwItems.rowCount() === 0) {
                                    VescIf.emitMessageDialog(
                                                "Upload Error",
                                                "This version of ENNOID-BMS Tool does not include any firmware " +
                                                "for your hardware version. You can either " +
                                                "upload a custom file or look for a later version of ENNOID-BMS " +
                                                "Tool that might support your hardware.",
                                                false)
                                    return;
                                }

                                if (hwItems.rowCount() === 1) {
                                    uploadDialog.title = "Warning"
                                    uploadDialogLabel.text =
                                            "Uploading new firmware will clear all settings on your ENNOID-BMS " +
                                            "and you have to do the configuration again. Do you want to " +
                                            "continue?"
                                    uploadDialog.open()
                                } else {
                                    uploadDialog.title = "Warning"
                                    uploadDialogLabel.text =
                                            "Uploading firmware for the wrong hardware version " +
                                            "WILL damage the ENNOID-BMS for sure. Are you sure that you have " +
                                            "chosen the correct hardware version?"
                                    uploadDialog.open()
                                }
                            } else if (swipeView.currentIndex == 1) {
                                if (customFwText.text.length > 0) {
                                    uploadDialog.title = "Warning"
                                    uploadDialogLabel.text =
                                            "Uploading firmware for the wrong hardware version " +
                                            "WILL damage the ENNOID-BMS for sure. Are you sure that you have " +
                                            "chosen the correct hardware version?"
                                    uploadDialog.open()
                                } else {
                                    VescIf.emitMessageDialog(
                                                "Error",
                                                "Please select a file",
                                                false, false)
                                }
                            } else if (swipeView.currentIndex == 2) {
                                if (blItems.rowCount() === 0) {
                                    VescIf.emitMessageDialog(
                                                "Upload Error",
                                                "This version of ENNOID-BMS Tool does not include any bootloader " +
                                                "for your hardware version.",
                                                false)
                                    return;
                                }

                                uploadDialog.title = "Warning"
                                uploadDialogLabel.text =
                                        "This will attempt to upload a bootloader to the connected VESC. " +
                                        "If the connected ENNOID-BMS already has a bootloader this will destroy " +
                                        "the bootloader and firmware updates cannot be done anymore. Do " +
                                        "you want to continue?"
                                uploadDialog.open()
                            }
                        }
                    }

                    Button {
                        id: cancelButton
                        text: qsTr("Cancel")
                        Layout.fillWidth: true
                        enabled: false

                        onClicked: {
                            mCommands.cancelFirmwareUpload()
                        }
                    }
                }

                Text {
                    Layout.fillWidth: true
                    id: versionText
                    color: "#e0e0e0"
                    text:
                        "FW   : \n" +
                        "HW   : \n" +
                        "UUID : "
                    font.family: "DejaVu Sans Mono"
                    verticalAlignment: Text.AlignVCenter
                }
            }
        }
    }

    Dialog {
        id: uploadDialog
        standardButtons: Dialog.Ok | Dialog.Cancel
        modal: true
        focus: true
        width: parent.width - 20
        closePolicy: Popup.CloseOnEscape

        x: (parent.width - width) / 2
        y: (parent.height - height) / 2

        Text {
            color: "#ffffff"
            id: uploadDialogLabel
            verticalAlignment: Text.AlignVCenter
            anchors.fill: parent
            wrapMode: Text.WordWrap
        }

        onAccepted: {
            if (swipeView.currentIndex == 0) {
                fwHelper.uploadFirmware(fwItems.get(fwBox.currentIndex).value, VescIf, false, false)
            } else if (swipeView.currentIndex == 1) {
                fwHelper.uploadFirmware(customFwText.text, VescIf, false, true)
            } else if (swipeView.currentIndex == 2) {
                fwHelper.uploadFirmware(blItems.get(blBox.currentIndex).value, VescIf, true, false)
            }
        }
    }

    function updateHw(hw) {
        var hws = fwHelper.getHardwares(hw)

        hwItems.clear()

        for (var name in hws) {
            if (name.indexOf("412") !== -1) {
                hwItems.insert(0, { key: name, value: hws[name] })
            } else {
                hwItems.append({ key: name, value: hws[name] })
            }
        }

        hwBox.currentIndex = 0
    }

    function updateBl(hw) {
        var bls = fwHelper.getBootloaders(hw)

        blItems.clear()

        for (var name in bls) {
            if (name.indexOf("412") !== -1) {
                blItems.insert(0, { key: name, value: bls[name] })
            } else {
                blItems.append({ key: name, value: bls[name] })
            }
        }

        blBox.currentIndex = 0
    }

    Connections {
        target: VescIf

        onFwUploadStatus: {
            if (isOngoing) {
                uploadText.text = status + " (" + parseFloat(progress * 100.0).toFixed(2) + " %)"
            } else {
                uploadText.text = status
            }

            uploadProgress.value = progress
            uploadButton.enabled = !isOngoing
            cancelButton.enabled = isOngoing
        }
    }

    Connections {
        target: mCommands

        onFwVersionReceived: {
            updateHw(hw)
            updateBl(hw)

            versionText.text =
                    "FW   : " + major + "." + minor + "\n" +
                    "HW   : " + hw + "\n" +
                    "UUID : " + Utility.uuid2Str(uuid, false)
        }
    }
}
