// "Add app to dock", reachable without opening Settings.
//
// The Settings page is the place to curate the whole dock -- reorder it, unpin
// things, change how it hides. Adding one application is a single decision made
// while looking at the dock, and routing it through a settings window means
// finding the page, then the card, then the box. This is that box, on its own.
//
// It embeds the same DockAppPicker the Dock page uses rather than growing a
// second search: the exclusion of already-pinned applications, the icon lookup
// and the "nothing until you type" behaviour are all already there, and two
// copies of them would drift.

import Quickshell
import Quickshell.Wayland
import QtQuick
import qs.config
import qs.services
import qs.modules.settings
import qs.widgets

PanelWindow {
    id: root

    readonly property bool open: ShellState.dockPickerOpen

    // The one place a pin is added from outside the Settings page. Returns
    // false for an id nothing installs, so the IPC caller hears about a typo
    // instead of the dock quietly gaining a hole -- DockBody drops a pin it
    // cannot resolve, so a bad id is invisible at runtime.
    function pin(id: string): bool {
        const wanted = String(id ?? "").trim();
        if (!wanted || !DesktopEntries.byId(wanted))
            return false;
        const stored = Settings.dockPinned;
        if (stored.indexOf(wanted) >= 0)
            return true;
        DesktopPreferences.set("dockPinned", stored.concat([wanted]));
        return true;
    }

    anchors { top: true; bottom: true; left: true; right: true }
    color: "transparent"
    exclusiveZone: 0
    exclusionMode: ExclusionMode.Ignore

    // Blurred by the `^qs-popover` rule in hypr/rules.lua; the scrim is painted
    // here rather than added to that rule, the same way the cheatsheet does it.
    WlrLayershell.namespace: "qs-popover-dock-picker"
    WlrLayershell.layer: WlrLayer.Overlay
    WlrLayershell.keyboardFocus: root.open
        ? WlrKeyboardFocus.Exclusive
        : WlrKeyboardFocus.None

    // Stays mapped for the length of the close animation, or it vanishes
    // instantly and only the opening is ever seen.
    property bool mapped: false
    visible: root.mapped

    onOpenChanged: {
        if (root.open) {
            unmapTimer.stop();
            root.mapped = true;
            picker.grab();
        } else {
            unmapTimer.restart();
        }
    }

    Timer {
        id: unmapTimer
        interval: Theme.durNormal
        onTriggered: root.mapped = false
    }

    Rectangle {
        anchors.fill: parent
        color: Theme.alpha(Theme.bgDark, Theme.overlayAlpha)
        opacity: root.open ? 1 : 0
        Behavior on opacity { NumberAnimation { duration: Theme.durNormal; easing.type: Easing.OutCubic } }

        MouseArea {
            anchors.fill: parent
            onClicked: ShellState.close()
        }
    }

    Rectangle {
        id: card

        anchors.horizontalCenter: parent.horizontalCenter
        // High rather than centred: the list grows downwards as you type, and a
        // centred card walks up the screen while you are reading it.
        y: Math.round(parent.height * 0.18)
        width: Math.min(root.width - 120, 520)
        height: header.height + picker.implicitHeight + 56

        radius: Theme.popoverRadius
        color: Theme.alpha(Theme.bgPopover, Theme.popoverAlpha)
        border.width: 1
        border.color: Theme.alpha(Theme.fg, 0.1)

        opacity: root.open ? 1 : 0
        scale: root.open ? 1 : 0.98
        Behavior on opacity { NumberAnimation { duration: Theme.durNormal; easing.type: Easing.OutCubic } }
        Behavior on scale { NumberAnimation { duration: Theme.durNormal; easing.type: Easing.OutCubic } }

        PrismEdge {
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.right: parent.right
            inset: Theme.popoverRadius
        }

        // Clicks on the card itself must not fall through to the scrim.
        MouseArea { anchors.fill: parent }

        Item {
            id: header

            anchors.top: parent.top
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.margins: 22
            height: title.implicitHeight

            Text {
                id: title
                text: "Add app to dock"
                color: Theme.fg
                font.family: Theme.fontFamily
                font.pixelSize: Theme.fontSizeLarge
                font.weight: Font.DemiBold
            }

            Text {
                anchors.right: parent.right
                anchors.verticalCenter: title.verticalCenter
                text: "Esc to close"
                color: Theme.fgMuted
                font.family: Theme.fontFamily
                font.pixelSize: Theme.fontSizeSmall
            }
        }

        DockAppPicker {
            id: picker

            anchors.top: header.bottom
            anchors.topMargin: 16
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.leftMargin: 22
            anchors.rightMargin: 22

            pinned: Settings.dockPinned
            onPicked: id => {
                root.pin(id);
                ShellState.close();
            }
        }
    }

    // A Shortcut rather than Keys.onEscapePressed on an item: the search box
    // owns Escape while it has focus (it clears the query first), and a key
    // handler on an ancestor would never see the second press.
    Shortcut {
        sequence: "Escape"
        enabled: root.open
        onActivated: ShellState.close()
    }
}
