/*
    SPDX-FileCopyrightText: 2021 Cyril Rossi <cyril.rossi@enioka.com>
    SPDX-FileCopyrightText: 2022 Marco Martin <mart@kde.org>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import QtQuick.Window

import org.kde.kirigami as Kirigami

QQC2.Control {
    id: delegate
    property Item viewPort
    readonly property string screenName: model.screenName
    readonly property int screenId: model.screenId
    property bool containsDrag
    property alias contentsLayout: contentsLayout

    width: Math.min(Kirigami.Units.gridUnit * 25, Math.floor(viewPort.width / Math.min(repeater.count, Math.floor(viewPort.width / (Kirigami.Units.gridUnit * 12)))))

    contentItem: ColumnLayout {
        id: contentsLayout
        width: Math.min(parent.width, Kirigami.Units.gridUnit * 15)

        Rectangle {
            id: screenRect
            Layout.fillWidth: true
            Layout.preferredHeight: width / 1.6
            color: Kirigami.Theme.backgroundColor
            border.color: Kirigami.Theme.textColor
            Rectangle {
                anchors.fill: parent
                z: 9
                color: "black"
                opacity: delegate.containsDrag ? 0.3 : 0
                Behavior on opacity {
                    OpacityAnimator {
                        duration: Kirigami.Units.longDuration
                        easing.type: Easing.InOutQuad
                    }
                }
            }

            Repeater {
                id: containmentRepeater
                model: containments

                Rectangle {
                    id: contRect
                    property real homeX
                    property real homeY
                    property string oldState
                    readonly property int edgeDistance: {
                        return (state === "left" || state === "right" ? width : height) * model.edgePosition;
                    }

                    width: moveButton.width
                    height: moveButton.height
                    border.color: Kirigami.Theme.textColor
                    color: Kirigami.Theme.backgroundColor
                    state: model.edge
                    z: state === "floating" ? 0 : 1
                    visible: !model.isDestroyed

                    HoverHandler {
                        cursorShape: Qt.OpenHandCursor
                    }
                    DragHandler {
                        id: dragHandler
                        property QQC2.Control targetDelegate

                        cursorShape: Qt.ClosedHandCursor
                        onActiveChanged: {
                            if (active) {
                                delegate.z = 1;
                            } else {
                                if (targetDelegate) {
                                    resetAnim.restart();
                                    containmentRepeater.model.moveContainementToScreen(model.containmentId, targetDelegate.screenId)
                                    targetDelegate.containsDrag = false;
                                    targetDelegate = null;
                                } else {
                                    resetAnim.restart();
                                }
                            }
                        }
                        onTranslationChanged: {
                            if (!active) {
                                if (targetDelegate) {
                                    targetDelegate.containsDrag = false;
                                    targetDelegate = null;
                                }
                                return;
                            }
                            let pos = contRect.mapToItem(delegate.parent, dragHandler.centroid.position.x, dragHandler.centroid.position.y);
                            let otherDelegate = delegate.parent.childAt(pos.x, pos.y);
                            if (targetDelegate && targetDelegate !== otherDelegate) {
                                targetDelegate.containsDrag = false;
                            }
                            if (!otherDelegate || otherDelegate === delegate) {
                                targetDelegate = null;
                            } else if (otherDelegate && otherDelegate !== delegate
                                && otherDelegate.hasOwnProperty("screenId")
                                && otherDelegate.hasOwnProperty("containsDrag")) {
                                targetDelegate = otherDelegate;
                                targetDelegate.containsDrag = true;
                            }
                        }
                    }
                    SequentialAnimation {
                        id: resetAnim
                        property var targetDelegatePos: dragHandler.targetDelegate
                                ? dragHandler.targetDelegate.contentsLayout.mapToItem(delegate.contentsLayout, 0, 0)
                                : Qt.point(0, 0)
                        ParallelAnimation {
                            XAnimator {
                                target: contRect
                                from: contRect.x
                                to: contRect.homeX + resetAnim.targetDelegatePos.x
                                duration: Kirigami.Units.longDuration
                                easing.type: Easing.InOutQuad
                            }
                            YAnimator {
                                target: contRect
                                from: contRect.y
                                to: contRect.homeY + resetAnim.targetDelegatePos.y
                                duration: Kirigami.Units.longDuration
                                easing.type: Easing.InOutQuad
                            }
                        }
                        PropertyAction {
                            target: delegate
                            property: "z"
                            value: 0
                        }
                    }

                    Image {
                        id: containmentImage
                        anchors {
                            fill: parent
                            margins: 1
                        }
                        // It needs to reload the image from disk when the file changes
                        cache: false
                        source: model.imageSource
                        fillMode: model.edge == "floating" ? Image.PreserveAspectCrop : Image.PreserveAspectFit
                    }

                    QQC2.Button {
                        id: moveButton
                        icon.name: "open-menu-symbolic"
                        visible: contextMenuRepeater.anyActionAvailable || removeItem.itemVisible
                        checked: contextMenu.visible
                        anchors {
                            right: parent.right
                            top: parent.top
                            topMargin: model.edge == "floating"
                                ? model.panelCountAtTop * moveButton.height + Kirigami.Units.largeSpacing
                                : 0
                            rightMargin: model.edge == "floating"
                                ? (moveButton.LayoutMirroring.enabled ? model.panelCountAtLeft : model.panelCountAtRight) * moveButton.height + Kirigami.Units.largeSpacing
                                : 0
                        }
                        onClicked: {
                            contextMenu.open()
                        }

                        QQC2.Menu {
                            id: contextMenu
                            y: moveButton.height
                            Repeater {
                                id: contextMenuRepeater
                                model: ShellContainmentModel

                                // There will always be at least one hidden action for the
                                // current screen; if there's any other, then we should
                                // display them.
                                property bool anyActionAvailable: count > 1

                                QQC2.MenuItem {
                                    text: edge == "floating"
                                        ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:inmenu", "Swap with Desktop on Screen %1", model.screenName)
                                        : i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:inmenu", "Move to Screen %1", model.screenName)
                                    visible: model.screenName !== delegate.screenName
                                    height: visible ? implicitHeight : 0
                                    onTriggered: {
                                        containmentRepeater.model.moveContainementToScreen(containmentId, screenId)
                                    }
                                }
                            }
                            QQC2.MenuSeparator {
                                visible: removeItem.visible && contextMenuRepeater.anyActionAvailable
                            }
                            QQC2.MenuItem {
                                id: removeItem
                                text: contRect.state === "floating"
                                    ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:inmenu", "Remove Desktop")
                                    : i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:inmenu", "Remove Panel")
                                icon.name: "edit-delete"
                                onTriggered: {
                                    if (contRect.state === "floating") {
                                        ShellContainmentModel.remove(screenId);
                                    } else {
                                        containments.remove(containmentId);
                                    }
                                }
                                // We read this variable elsewhere to know if this item
                                // would be visible if the context menu were to be shown.
                                property bool itemVisible: contRect.state !== "floating" || !model.active
                                visible: itemVisible
                            }
                        }
                    }

                    states: [
                        State {
                            name: "floating"
                            PropertyChanges {
                                target: contRect;
                                width: screenRect.width
                                height: screenRect.height
                                color: "transparent"
                            }
                        },
                        State {
                            name: "top"
                            PropertyChanges {
                                target: contRect;
                                width: screenRect.width
                                y: homeY
                                homeX: 0
                                homeY: contRect.edgeDistance
                            }
                        },
                        State {
                            name: "right"
                            PropertyChanges {
                                target: contRect;
                                x: homeX
                                homeX: screenRect.width - contRect.width - contRect.edgeDistance;
                                height: screenRect.height
                                homeY: 0
                            }
                        },
                        State {
                            name: "bottom"
                            PropertyChanges {
                                target: contRect;
                                y: homeY
                                homeX: 0
                                homeY: screenRect.height - contRect.height - contRect.edgeDistance;
                                width: screenRect.width
                            }
                        },
                        State {
                            name: "left"
                            PropertyChanges {
                                target: contRect;
                                height: screenRect.height
                                x: homeX
                                homeX: contRect.edgeDistance
                                homeY: 0
                            }
                        }
                    ]
                }
            }
        }
        QQC2.Label {
            Layout.fillWidth: true
            horizontalAlignment: Text.AlignHCenter
            wrapMode: Text.WordWrap
            text: model.isPrimary
                ? i18ndc("plasma_shell_org.kde.plasma.desktop", "@info % is screen name", "%1 (primary)", model.screenName)
                : model.screenName
            textFormat: Text.PlainText
        }
    }
}
