// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import WelcomeScreen 1.0
import ExampleCheckout 1.0

Item {
    id: root
    width: Constants.thumbnailSize
    height: Constants.thumbnailSize
    clip: true
    state: "normal"

    property bool textWrapped: false
    property bool hasDescription: false
    property bool hasPath: false
    property bool hasUpdate: false
    property bool downloadable: false
    property int numberOfPanels: 3

    enum Type {
        RecentProject,
        Example,
        Tutorial
    }

    property int type: ThumbnailDelegate.Type.RecentProject

    property alias projectNameLabelText: projectNameLabel.text
    property alias projectPathLabelText: projectPathLabel.text
    property alias thumbnailPlaceholderSource: thumbnailPlaceholder.source

    property alias downloadUrl: downloader.url
    property alias tempFile: downloader.outputFile
    property alias completeBaseName: downloader.completeBaseName
    property alias targetPath: extractor.targetPath

    property alias bannerLabelText: updateText.text

    enum Panel {
        InBetween,
        Download,
        Main,
        Details
    }

    property int currentPanel: ThumbnailDelegate.Panel.Main

    signal clicked()
    signal rightClicked()

    function startDownload() {
        twirlToDownloadAnimation.start()
        downloadPanel.text = downloadPanel.downloadText
        downloadPanel.allowCancel = true
        downloadPanel.value = Qt.binding(function() { return downloader.progress })
        downloader.start()
        mouseArea.enabled = false
    }

    function thumbnailClicked() {
        if (root.type === ThumbnailDelegate.Type.RecentProject
            || root.type === ThumbnailDelegate.Type.Tutorial)
            root.clicked() // open recent project/tutorial

        if (Constants.loadingProgress < 95)
            return
        if (root.type === ThumbnailDelegate.Type.Example) {
            if (root.downloadable
                && !downloadButton.alreadyDownloaded
                && !downloadButton.downloadUnavailable) {
                root.startDownload()
            } else if (downloadButton.alreadyDownloaded) {
                root.clicked() // open example
            }
        }
    }

    MouseArea {
        id: mouseArea
        anchors.fill: parent
        propagateComposedEvents: true
        hoverEnabled: true
        acceptedButtons: Qt.LeftButton | Qt.RightButton

        Connections {
            target: mouseArea
            function onClicked(mouse) {
                if (mouse.button === Qt.RightButton)
                    root.rightClicked()
                else
                    root.thumbnailClicked(mouse)
            }
        }
    }

    CustomDialog {
        id: overwriteDialog
        title: qsTr("Overwrite Example?")
        standardButtons: Dialog.Yes | Dialog.No
        modal: true
        anchors.centerIn: parent

        onAccepted: root.startDownload()

        Text {
            width: parent.width
            horizontalAlignment: Text.AlignHCenter
            font.pixelSize: 12
            color: Constants.currentGlobalText
            text: qsTr("Example already exists.<br>Do you want to replace it?")
        }
    }

    Item {
        id: canvas
        width: Constants.thumbnailSize
        height: Constants.thumbnailSize * root.numberOfPanels

        DownloadPanel {
            id: downloadPanel

            height: Constants.thumbnailSize
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: mainPanel.top
            radius: 10
            value: downloader.progress

            readonly property string downloadText: qsTr("Downloading...")
            readonly property string extractText: qsTr("Extracting...")

            onCancelRequested: downloader.cancel()
        }

        Rectangle {
            id: mainPanel
            height: Constants.thumbnailSize
            anchors.left: parent.left
            anchors.right: parent.right
            color: "#ea8c8c"
            radius: 10

            property bool multiline: (projectNameLabelMetric.width >= projectNameLabel.width)

            TextMetrics {
                id: projectNameLabelMetric
                text: projectNameLabel.text
                font: projectNameLabel.font
            }

            Image {
                id: thumbnailPlaceholder
                anchors.fill: parent
                anchors.bottomMargin: Constants.imageBottomMargin
                anchors.rightMargin: Constants.thumbnailMargin
                anchors.leftMargin: Constants.thumbnailMargin
                anchors.topMargin: Constants.thumbnailMargin
                fillMode: Image.PreserveAspectFit
                verticalAlignment: Image.AlignTop
                mipmap: true
            }

            Rectangle {
                id: projectNameBackground
                height: mainPanel.multiline && !root.hasPath ? Constants.titleHeightMultiline
                                                             : Constants.titleHeight
                color: "#e5b0e4"
                radius: 3
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: thumbnailPlaceholder.bottom
                anchors.topMargin: Constants.titleBackgroundTopMargin
                anchors.leftMargin: Constants.thumbnailMargin
                anchors.rightMargin: Constants.thumbnailMargin

                Text {
                    id: projectNameLabel
                    color: Constants.currentGlobalText
                    text: typeof(displayName) === "undefined" ? projectName : displayName
                    elide: root.hasPath ? Text.ElideMiddle : Text.ElideRight
                    font.pixelSize: 16
                    wrapMode: Text.WordWrap
                    maximumLineCount: 2
                    clip: false
                    anchors.verticalCenter: parent.verticalCenter
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.leftMargin: Constants.titleMargin
                    anchors.rightMargin: Constants.titleMargin

                    MouseArea {
                        id: projectNameMouseArea
                        anchors.fill: parent
                        hoverEnabled: true
                        // Only enable the MouseArea if label actually contains text
                        enabled: projectNameLabel.text !== "" ? true : false

                        Connections {
                            target: projectNameMouseArea
                            onClicked: root.thumbnailClicked()
                        }
                    }

                    ToolTip {
                        id: projectNameToolTip
                        y: -projectNameToolTip.height
                        visible: projectNameMouseArea.containsMouse && projectNameLabel.truncated
                        text: projectNameLabel.text
                        delay: 1000
                        height: 20
                        background: Rectangle {
                            color: Constants.currentToolTipBackground
                            border.color: Constants.currentToolTipOutline
                            border.width: 1
                        }
                        contentItem: Text {
                            color: Constants.currentToolTipText
                            text: projectNameToolTip.text
                            verticalAlignment: Text.AlignVCenter
                        }
                    }
                }

                DownloadButton {
                    id: downloadButton

                    anchors.right: parent.right
                    anchors.top: parent.top
                    visible: root.downloadable
                    enabled: !downloadButton.downloadUnavailable

                    globalHover: (mouseArea.containsMouse || projectNameMouseArea.containsMouse)
                                 && !downloadButton.alreadyDownloaded
                                 && !downloadButton.downloadUnavailable
                                 && !downloadButton.updateAvailable

                    alreadyDownloaded: extractor.targetFolderExists
                    downloadUnavailable: !downloader.available
                    updateAvailable: downloader.lastModified > extractor.birthTime

                    FileDownloader {
                        id: downloader
                        downloadEnabled: $dataModel.downloadEnabled()
                        probeUrl: true

                        onFinishedChanged: {
                            downloadPanel.text = downloadPanel.extractText
                            downloadPanel.allowCancel = false
                            downloadPanel.value = Qt.binding(function() { return extractor.progress })
                            extractor.extract()
                        }

                        onDownloadStarting: {
                            $dataModel.usageStatisticsDownloadExample(downloader.name)
                        }

                        onDownloadCanceled: {
                            downloadPanel.text = ""
                            downloadPanel.value = 0
                            twirlToMainAnimation.start()
                            mouseArea.enabled = true
                        }
                    }

                    FileExtractor {
                        id: extractor
                        archiveName: downloader.completeBaseName
                        sourceFile: downloader.outputFile
                        targetPath: $dataModel.targetPath()
                        alwaysCreateDir: true
                        clearTargetPathContents: true
                        onFinishedChanged: {
                            twirlToMainAnimation.start()
                            root.bannerLabelText = qsTr("Recently Downloaded")
                            mouseArea.enabled = true
                        }
                    }

                    Connections {
                        target: downloadButton
                        onDownloadClicked: {
                            if (downloadButton.alreadyDownloaded) {
                                overwriteDialog.open()
                            } else {
                                if (downloadButton.enabled)
                                    root.startDownload()
                            }
                        }
                    }

                    Connections {
                        target: $dataModel
                        onTargetPathMustChange: (path) => {
                            extractor.changeTargetPath(path)
                        }
                    }
                }
            }

            Text {
                id: projectPathLabel
                visible: root.hasPath
                color: Constants.currentBrand
                text: typeof(prettyFilePath) === "undefined" ? "" : prettyFilePath
                elide: Text.ElideLeft
                renderType: Text.NativeRendering
                font.pixelSize: 16
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: projectNameBackground.bottom
                anchors.topMargin: 5
                anchors.rightMargin: Constants.thumbnailMargin
                anchors.leftMargin: Constants.thumbnailMargin
                leftPadding: 5

                MouseArea {
                    id: projectPathMouseArea
                    anchors.fill: parent
                    hoverEnabled: true
                    // Only enable the MouseArea if label actually contains text
                    enabled: projectPathLabel.text !== ""
                }

                ToolTip {
                    id: projectPathToolTip
                    y: -projectPathToolTip.height
                    visible: projectPathMouseArea.containsMouse && projectPathLabel.truncated
                    text: projectPathLabel.text
                    delay: 1000
                    height: 20
                    background: Rectangle {
                        color: Constants.currentToolTipBackground
                        border.color: Constants.currentToolTipOutline
                        border.width: 1
                    }
                    contentItem: Text {
                        color: Constants.currentToolTipText
                        text: projectPathToolTip.text
                        verticalAlignment: Text.AlignVCenter
                    }
                }
            }

            Rectangle {
                id: updateBackground
                width: 200
                height: 25
                visible: root.bannerLabelText !== ""
                color: Constants.currentBrand
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: parent.top
                anchors.topMargin: 0
                anchors.rightMargin: Constants.thumbnailMargin
                anchors.leftMargin: Constants.thumbnailMargin

                Text {
                    id: updateText
                    color: Constants.darkActiveGlobalText
                    text: typeof(displayName) === "bannerText" ? "" : bannerText
                    anchors.fill: parent
                    font.pixelSize: 12
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
            }
        }

        Rectangle {
            id: detailsPanel
            height: Constants.thumbnailSize
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.top: mainPanel.bottom
            color: Constants.currentNormalThumbnailBackground
            radius: 10

            Text {
                id: recentProjectInfo
                color: Constants.currentGlobalText
                linkColor: Constants.currentBrand
                text: typeof(description) === "undefined" ? "" : description
                anchors.fill: parent
                font.pixelSize: 12
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignTop
                wrapMode: Text.WordWrap
                anchors.margins: Constants.thumbnailMargin
                anchors.topMargin: 25

                MouseArea {
                    anchors.fill: parent
                    acceptedButtons: Qt.NoButton
                    cursorShape: recentProjectInfo.hoveredLink === "" ?  Qt.ArrowCursor : Qt.PointingHandCursor
                }

                Connections {
                    target: recentProjectInfo
                    onLinkActivated: (link)=>  Constants.projectModel.showLink(link)
                }
            }

            TagArea {
                id: tagArea
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.bottom: parent.bottom
                anchors.bottomMargin: Constants.thumbnailMargin
                anchors.rightMargin: Constants.thumbnailMargin
                anchors.leftMargin: Constants.thumbnailMargin
                tags: typeof(tagData) === "undefined" ? "" : tagData.split(",")
            }
        }
    }

    states: [
        State {
            name: "normal"
            when: !mouseArea.containsMouse && !(mouseArea.pressedButtons & Qt.LeftButton)
                  && !projectPathMouseArea.containsMouse && !projectNameMouseArea.containsMouse
                  && !downloadButton.isHovered && !twirlButtonDown.isHovered
                  && !twirlButtonUp.isHovered

            PropertyChanges {
                target: mainPanel
                color: Constants.currentNormalThumbnailBackground
                border.width: 0
            }
            PropertyChanges {
                target: detailsPanel
                color: Constants.currentNormalThumbnailBackground
                border.width: 0
            }
            PropertyChanges {
                target: projectNameBackground
                color: Constants.currentNormalThumbnailLabelBackground
            }
            PropertyChanges {
                target: twirlButtonDown
                parentHovered: false
            }
            PropertyChanges {
                target: twirlButtonUp
                parentHovered: false
            }
        },
        State {
            name: "hover"
            when: (mouseArea.containsMouse || projectPathMouseArea.containsMouse
                   || projectNameMouseArea.containsMouse || downloadButton.isHovered
                   || twirlButtonDown.isHovered || twirlButtonUp.isHovered)
                  && !(mouseArea.pressedButtons & Qt.LeftButton) && !root.hasDescription

            PropertyChanges {
                target: mainPanel
                color: Constants.currentHoverThumbnailBackground
                border.width: 0
            }
            PropertyChanges {
                target: detailsPanel
                color: Constants.currentHoverThumbnailBackground
                border.width: 0
            }
            PropertyChanges {
                target: projectNameBackground
                color: Constants.currentHoverThumbnailLabelBackground
            }
            PropertyChanges {
                target: thumbnailPlaceholder
                visible: true
            }
            PropertyChanges {
                target: twirlButtonDown
                parentHovered: true
            }
            PropertyChanges {
                target: twirlButtonUp
                parentHovered: true
            }
        },
        State {
            name: "press"
            when: (mouseArea.pressedButtons & Qt.LeftButton) && !root.hasDescription

            PropertyChanges {
                target: mainPanel
                color: Constants.currentHoverThumbnailBackground
                border.color: Constants.currentBrand
                border.width: 2
            }
            PropertyChanges {
                target: detailsPanel
                color: Constants.currentHoverThumbnailBackground
                border.color: Constants.currentBrand
                border.width: 2
            }
            PropertyChanges {
                target: projectNameBackground
                color: Constants.currentBrand
            }
            PropertyChanges {
                target: thumbnailPlaceholder
                visible: true
            }
            PropertyChanges {
                target: projectNameLabel
                color: Constants.darkActiveGlobalText
            }
        },
        State {
            name: "hoverDescription"
            when: mouseArea.containsMouse && !(mouseArea.pressedButtons & Qt.LeftButton)
                  && root.hasDescription

            PropertyChanges {
                target: mainPanel
                color: Constants.currentHoverThumbnailBackground
                border.width: 0
            }
            PropertyChanges {
                target: projectNameBackground
                color: Constants.currentHoverThumbnailLabelBackground
            }
            PropertyChanges {
                target: thumbnailPlaceholder
                visible: true
            }
        },
        State {
            name: "pressDescription"
            when: (mouseArea.pressedButtons & Qt.LeftButton) && root.hasDescription

            PropertyChanges {
                target: mainPanel
                color: Constants.currentHoverThumbnailBackground
                border.color: Constants.currentBrand
                border.width: 2
            }
            PropertyChanges {
                target: projectNameBackground
                color: Constants.currentBrand
            }
            PropertyChanges {
                target: thumbnailPlaceholder
                visible: true
            }
        }
    ]

    TwirlButton {
        id: twirlButtonDown
        height: 20
        visible: root.currentPanel === ThumbnailDelegate.Panel.Main
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom

        Connections {
            target: twirlButtonDown
            onTriggerRelease: twirlToDetailsAnimation.start()
        }
    }

    TwirlButton {
        id: twirlButtonUp
        height: 20
        visible: root.currentPanel === ThumbnailDelegate.Panel.Details
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top: parent.top
        rotation: 180

        Connections {
            target: twirlButtonUp
            onTriggerRelease: twirlToMainAnimation.start()
        }
    }

    NumberAnimation {
        id: twirlToDetailsAnimation
        target: canvas
        property: "y"
        easing.bezierCurve: [0.972,-0.176,0.0271,1.16,1,1]
        duration: 250
        alwaysRunToEnd: true
        to: -Constants.thumbnailSize // dynamic size because of rescale - needs to be inverted because animation goes into negative range
        from: canvas.y
    }

    NumberAnimation {
        id: twirlToMainAnimation
        target: canvas
        property: "y"
        easing.bezierCurve: [0.972,-0.176,0.0271,1.16,1,1]
        alwaysRunToEnd: true
        duration: 250
        to: 0
        from: canvas.y
    }

    NumberAnimation {
        id: twirlToDownloadAnimation
        target: canvas
        property: "y"
        easing.bezierCurve: [0.972,-0.176,0.0271,1.16,1,1]
        alwaysRunToEnd: true
        duration: 250
        to: Constants.thumbnailSize
        from: canvas.y
    }

    Connections {
        target: twirlToDetailsAnimation
        onStarted: root.currentPanel = ThumbnailDelegate.Panel.InBetween
        onFinished: {
            root.currentPanel = ThumbnailDelegate.Panel.Details
            canvas.y = Qt.binding(function() {return -Constants.thumbnailSize })
        }
    }

    Connections {
        target: twirlToMainAnimation
        onStarted: root.currentPanel = ThumbnailDelegate.Panel.InBetween
        onFinished: {
            root.currentPanel = ThumbnailDelegate.Panel.Main
            canvas.y = Qt.binding(function() {return 0 })
        }
    }

    Connections {
        target: twirlToDownloadAnimation
        onStarted: root.currentPanel = ThumbnailDelegate.Panel.InBetween
        onFinished: {
            root.currentPanel = ThumbnailDelegate.Panel.Download
            canvas.y = Qt.binding(function() {return Constants.thumbnailSize })
        }
    }
}
