import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
import qs.Widgets

PanelWindow {
    id: root

    default property alias content: menuColumn.children

    property var anchorItem: null
    property real dockVisibleHeight: 40
    property int margin: 10
    property string layerNamespace: "dms:dock-context-menu"
    property real menuMaxWidth: 400
    property real menuMinWidth: 180

    property point anchorPos: Qt.point(screen ? screen.width / 2 : 0, screen ? screen.height - 100 : 0)

    function show(button, dockHeight, dockScreen) {
        if (dockScreen)
            screen = dockScreen;
        anchorItem = button;
        dockVisibleHeight = dockHeight || 40;
        visible = true;
    }

    function close() {
        visible = false;
    }

    function findDockBackground(item) {
        if (!item)
            return null;
        if (item.objectName === "dockBackground")
            return item;
        for (let i = 0; i < item.children.length; i++) {
            const found = findDockBackground(item.children[i]);
            if (found)
                return found;
        }
        return null;
    }

    function updatePosition() {
        if (!anchorItem || !screen) {
            anchorPos = Qt.point(screen ? screen.width / 2 : 0, screen ? screen.height - 100 : 0);
            return;
        }

        const dockWindow = anchorItem.Window.window;
        if (!dockWindow) {
            anchorPos = Qt.point(screen.width / 2, screen.height - 100);
            return;
        }

        const buttonPosInDock = anchorItem.mapToItem(dockWindow.contentItem, 0, 0);
        const dockBackground = findDockBackground(dockWindow.contentItem);
        const actualDockHeight = dockBackground ? dockBackground.height : root.dockVisibleHeight;
        const actualDockWidth = dockBackground ? dockBackground.width : dockWindow.width;
        const dockMargin = SettingsData.dockMargin + 16;

        // Connected mode hosts the dock inside the fullscreen frame surface, inset from the
        // screen edge. Anchor off the dock body's real position instead of the screen edge.
        const dockBgPos = dockBackground ? dockBackground.mapToItem(dockWindow.contentItem, 0, 0) : null;
        const frameHosted = dockBgPos && dockWindow.width >= screen.width - 1 && dockWindow.height >= screen.height - 1;
        let x = 0;
        let y = 0;

        switch (SettingsData.dockPosition) {
        case SettingsData.Position.Left:
            {
                const dockTopMargin = Math.round((screen.height - dockWindow.height) / 2);
                x = frameHosted ? (dockBgPos.x + actualDockWidth + dockMargin + 20) : (actualDockWidth + dockMargin + 20);
                y = dockTopMargin + buttonPosInDock.y + anchorItem.height / 2;
                break;
            }
        case SettingsData.Position.Right:
            {
                const dockTopMargin = Math.round((screen.height - dockWindow.height) / 2);
                x = frameHosted ? (dockBgPos.x - dockMargin - 20) : (screen.width - actualDockWidth - dockMargin - 20);
                y = dockTopMargin + buttonPosInDock.y + anchorItem.height / 2;
                break;
            }
        case SettingsData.Position.Top:
            {
                const dockLeftMargin = Math.round((screen.width - dockWindow.width) / 2);
                x = dockLeftMargin + buttonPosInDock.x + anchorItem.width / 2;
                y = frameHosted ? (dockBgPos.y + actualDockHeight + dockMargin + 20) : (actualDockHeight + dockMargin + 20);
                break;
            }
        case SettingsData.Position.Bottom:
        default:
            {
                const dockLeftMargin = Math.round((screen.width - dockWindow.width) / 2);
                x = dockLeftMargin + buttonPosInDock.x + anchorItem.width / 2;
                y = frameHosted ? (dockBgPos.y - dockMargin - 20) : (screen.height - actualDockHeight - dockMargin - 20);
                break;
            }
        }

        anchorPos = Qt.point(x, y);
    }

    onAnchorItemChanged: updatePosition()
    onVisibleChanged: {
        if (visible)
            updatePosition();
    }

    WindowBlur {
        targetWindow: root
        blurX: menuContainer.x
        blurY: menuContainer.y
        blurWidth: root.visible ? menuContainer.width : 0
        blurHeight: root.visible ? menuContainer.height : 0
        blurRadius: Theme.cornerRadius
    }

    WlrLayershell.namespace: root.layerNamespace
    WlrLayershell.layer: WlrLayershell.Overlay
    WlrLayershell.exclusiveZone: -1
    WlrLayershell.keyboardFocus: WlrKeyboardFocus.None

    screen: null
    visible: false
    color: "transparent"
    anchors {
        top: true
        left: true
        right: true
        bottom: true
    }

    Rectangle {
        id: menuContainer

        readonly property bool isVertical: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right

        x: {
            if (!isVertical) {
                const want = root.anchorPos.x - width / 2;
                return Math.max(10, Math.min(root.width - width - 10, want));
            }
            if (SettingsData.dockPosition === SettingsData.Position.Right)
                return Math.max(10, root.anchorPos.x - width + 30);
            return Math.min(root.width - width - 10, root.anchorPos.x - 30);
        }
        y: {
            if (isVertical) {
                const want = root.anchorPos.y - height / 2;
                return Math.max(10, Math.min(root.height - height - 10, want));
            }
            if (SettingsData.dockPosition === SettingsData.Position.Bottom)
                return Math.max(10, root.anchorPos.y - height + 30);
            return Math.min(root.height - height - 10, root.anchorPos.y - 30);
        }

        width: Math.min(root.menuMaxWidth, Math.max(root.menuMinWidth, menuColumn.implicitWidth + Theme.spacingS * 2))
        height: menuColumn.implicitHeight + Theme.spacingS * 2
        color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
        radius: Theme.cornerRadius
        border.color: BlurService.borderColor
        border.width: BlurService.borderWidth

        opacity: root.visible ? 1 : 0
        visible: opacity > 0

        Behavior on opacity {
            NumberAnimation {
                duration: Theme.shortDuration
                easing.type: Theme.emphasizedEasing
            }
        }

        Rectangle {
            anchors.fill: parent
            anchors.topMargin: 4
            anchors.leftMargin: 2
            anchors.rightMargin: -2
            anchors.bottomMargin: -4
            radius: parent.radius
            color: Qt.rgba(0, 0, 0, 0.15)
            z: -1
        }

        Column {
            id: menuColumn
            width: parent.width - Theme.spacingS * 2
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.top: parent.top
            anchors.topMargin: Theme.spacingS
            spacing: 1
        }
    }

    MouseArea {
        anchors.fill: parent
        z: -1
        onClicked: root.close()
    }
}
