// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: LGPL-2.0-or-later

import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as QQC2
import Qt5Compat.GraphicalEffects

import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.ksvg 1.0 as KSvg

import org.kde.plasma.components 3.0 as PC3
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio

import '../private'

Item {
    id: root
    property Folio.HomeScreen folio

    property var homeScreen

    property int pageNum
    property int row
    property int column

    property real widgetWidth
    property real widgetHeight
    property real widgetX
    property real widgetY

    property real topWidgetBackgroundPadding
    property real bottomWidgetBackgroundPadding
    property real leftWidgetBackgroundPadding
    property real rightWidgetBackgroundPadding

    property Folio.FolioPageDelegate pageDelegate
    property Folio.FolioWidget widget
    property var pageModel

    signal removeRequested()
    signal closed()
    readonly property int longAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)

    function startOpen() {
        // prevent config overlay if lock layout is enabled
        if (folio.FolioSettings.lockLayout) return;
        configOverlay.open();
    }

    function fullyOpen() {
        configPopup.open();
        configOverlay.close();
    }

    // HACK: this shows the config when we are in the "press to hold" state, prior to mouse release
    // we can't just open the popup, because the potential drag-and-drop swipe would get lost
    MouseArea {
        id: configOverlay
        parent: root.homeScreen
        anchors.fill: parent

        width: configPopup.width
        height: configPopup.height

        opacity: 0
        visible: opacity > 0

        // in case this gets stuck open over the homescreen, just close on tap
        onClicked: close()

        MobileShell.MotionNumberAnimation on opacity { id: configOverlayOpacityAnim; type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration }

        function open() {
            configOverlayOpacityAnim.to = 1;
            configOverlayOpacityAnim.restart();
        }

        function animClose() {
            if (opacity !== 0) {
                configOverlayOpacityAnim.to = 0;
                configOverlayOpacityAnim.restart();
            }
        }

        function close() {
            opacity = 0;
        }

        Connections {
            target: folio.HomeScreenState

            // if we are starting drag-and-drop, close the menu immediately
            function onDelegateDragStarted() {
                configOverlay.animClose();
                root.closed();
            }
        }

        // the config overlay
        FastBlur {
            anchors.fill: parent
            source: configPopup.contentItem
            radius: 0
        }
    }

    // this is the actual interactive popup for widget settings, only
    // opened when the user releases their press (and doesn't drag)
    QQC2.Popup {
        id: configPopup
        width: root.homeScreen.width
        height: root.homeScreen.height
        parent: root.homeScreen

        onClosed: {
            configOverlay.close(); // ensure overlay is closed
            root.closed();
        }

        topPadding: 0
        bottomPadding: 0
        leftPadding: 0
        rightPadding: 0

        closePolicy: QQC2.Popup.CloseOnEscape | QQC2.Popup.CloseOnPressOutsideParent

        readonly property real barWidth: Kirigami.Units.gridUnit * 3.5
        readonly property real barSpacing: Kirigami.Units.largeSpacing
        readonly property real minimumBarLength: Kirigami.Units.gridUnit * 8

        background: Item {}
        QQC2.Overlay.modal: Item {}

        exit: Transition {
            MobileShell.MotionNumberAnimation { property: "opacity"; type: MobileShell.Motion.EffectsDefault; duration: root.longAnimationDuration; from: 1.0; to: 0.0 }
        }

        Connections {
            target: folio.HomeScreenState

            // don't show config overlay if we have navigated to another page
            function onCurrentPageChanged() {
                if (configPopup.visible) {
                    configPopup.close();
                }
            }
        }

        contentItem: MouseArea {
            id: configItem

            onClicked: configPopup.close()

            WidgetResizeHandleFrame {
                id: resizeFrame
                folio: root.folio
                anchors.fill: parent

                widgetWidth: root.widgetWidth
                widgetHeight: root.widgetHeight
                widgetX: root.widgetX + root.leftWidgetBackgroundPadding
                widgetY: root.widgetY + root.topWidgetBackgroundPadding

                widgetTopMargin: root.topWidgetBackgroundPadding
                widgetBottomMargin: root.bottomWidgetBackgroundPadding
                widgetLeftMargin: root.leftWidgetBackgroundPadding
                widgetRightMargin: root.rightWidgetBackgroundPadding

                widgetRow: root.row
                widgetColumn: root.column
                widgetGridWidth: root.widget.gridWidth
                widgetGridHeight: root.widget.gridHeight

                onWidgetChangeAfterDrag: (widgetRow, widgetColumn, widgetGridWidth, widgetGridHeight) => {
                    if (resizeFrame.lockDrag !== null) triggerWidgetChanges(widgetRow, widgetColumn, widgetGridWidth, widgetGridHeight);
                }

                function triggerWidgetChanges(widgetRow, widgetColumn, widgetGridWidth, widgetGridHeight) {
                    root.pageModel.moveAndResizeWidgetDelegate(
                        root.pageDelegate,
                        widgetRow,
                        widgetColumn,
                        widgetGridWidth,
                        widgetGridHeight
                    );
                }
            }

            PC3.Button {
                id: button
                icon.name: 'settings-configure'
                text: i18n("Options")
                display: (resizeFrame.handleContainer.width > Kirigami.Units.gridUnit * 7) ? PC3.Button.TextBesideIcon : PC3.Button.IconOnly

                readonly property var handleContainer: resizeFrame.handleContainer
                x: Math.round(handleContainer.x + (handleContainer.width / 2) - (width / 2))
                y: Math.round(handleContainer.y + (handleContainer.height / 2) - (height / 2))

                onClicked: contextMenuDialog.open()
            }

            Kirigami.Dialog {
                id: contextMenuDialog
                preferredWidth: Kirigami.Units.gridUnit * 20
                padding: 0
                title: i18n("Widget Options")

                // workaround: remove background so that it doesn't remain if the widget is deleted (and this is de-initialized without closing)
                QQC2.Overlay.modal: null

                // close parent dialog too
                onClosed: configPopup.close()

                ColumnLayout {
                    id: column
                    spacing: 0

                    Repeater {
                        model: root.widget.applet ? [...root.widget.applet.contextualActions, configureAppletAction, removeDelegateAction] : [removeDelegateAction]

                        delegate: QQC2.ItemDelegate {
                            Layout.fillWidth: true
                            Layout.preferredHeight: Kirigami.Units.gridUnit * 2

                            action: modelData
                            text: modelData.text
                            icon.name: modelData.icon.name

                            icon.width: Kirigami.Units.gridUnit
                            icon.height: Kirigami.Units.gridUnit

                            leftPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
                            rightPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing

                            onClicked: contextMenuDialog.close()
                        }
                    }
                }
            }
        }
    }

    Kirigami.Action {
        id: removeDelegateAction
        icon.name: 'edit-delete-remove'
        text: i18n("Remove widget")
        onTriggered: root.removeRequested()
    }

    Kirigami.Action {
        id: configureAppletAction
        icon.name: 'settings-configure'
        text: i18n("Configure widget")
        onTriggered: root.widget.applet.internalAction('configure').trigger();
    }
}
