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

Item {
    id: root

    visible: false

    property bool spotlightOpen: false
    property bool keyboardActive: false
    property bool contentVisible: false
    property var spotlightContent: launcherContentLoader.item
    property bool openedFromOverview: false
    property bool isClosing: false
    property bool _pendingInitialize: false
    property string _pendingQuery: ""
    property string _pendingMode: ""
    readonly property bool unloadContentOnClose: SettingsData.dankLauncherV2UnloadOnClose

    readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
    readonly property var effectiveScreen: launcherWindow.screen
    readonly property real screenWidth: effectiveScreen?.width ?? 1920
    readonly property real screenHeight: effectiveScreen?.height ?? 1080
    readonly property real dpr: effectiveScreen ? CompositorService.getScreenScale(effectiveScreen) : 1

    readonly property int baseWidth: {
        switch (SettingsData.dankLauncherV2Size) {
        case "micro":
            return 500;
        case "medium":
            return 720;
        case "large":
            return 860;
        default:
            return 620;
        }
    }
    readonly property int baseHeight: {
        switch (SettingsData.dankLauncherV2Size) {
        case "micro":
            return 480;
        case "medium":
            return 720;
        case "large":
            return 860;
        default:
            return 600;
        }
    }
    readonly property int modalWidth: Math.min(baseWidth, screenWidth - 100)
    readonly property int modalHeight: Math.min(baseHeight, screenHeight - 100)
    readonly property real modalX: (screenWidth - modalWidth) / 2
    readonly property real modalY: (screenHeight - modalHeight) / 2

    readonly property color backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
    readonly property real cornerRadius: Theme.cornerRadius
    readonly property color borderColor: {
        if (!SettingsData.dankLauncherV2BorderEnabled)
            return Theme.outlineMedium;
        switch (SettingsData.dankLauncherV2BorderColor) {
        case "primary":
            return Theme.primary;
        case "secondary":
            return Theme.secondary;
        case "outline":
            return Theme.outline;
        case "surfaceText":
            return Theme.surfaceText;
        default:
            return Theme.primary;
        }
    }
    readonly property int borderWidth: SettingsData.dankLauncherV2BorderEnabled ? SettingsData.dankLauncherV2BorderThickness : 0

    signal dialogClosed

    function _ensureContentLoadedAndInitialize(query, mode) {
        _pendingQuery = query || "";
        _pendingMode = mode || "";
        _pendingInitialize = true;
        contentVisible = true;
        launcherContentLoader.active = true;

        if (spotlightContent) {
            _initializeAndShow(_pendingQuery, _pendingMode);
            _pendingInitialize = false;
        }
    }

    function _initializeAndShow(query, mode) {
        if (!spotlightContent)
            return;
        contentVisible = true;
        spotlightContent.searchField.forceActiveFocus();

        var targetQuery = "";

        if (query) {
            targetQuery = query;
        } else if (SettingsData.rememberLastQuery) {
            targetQuery = SessionData.launcherLastQuery || "";
        }

        if (spotlightContent.searchField) {
            spotlightContent.searchField.text = targetQuery;
        }
        if (spotlightContent.controller) {
            var targetMode = mode || SessionData.launcherLastMode || "all";
            spotlightContent.controller.searchMode = targetMode;
            spotlightContent.controller.activePluginId = "";
            spotlightContent.controller.activePluginName = "";
            spotlightContent.controller.pluginFilter = "";
            spotlightContent.controller.fileSearchType = "all";
            spotlightContent.controller.fileSearchExt = "";
            spotlightContent.controller.fileSearchFolder = "";
            spotlightContent.controller.fileSearchSort = "score";
            spotlightContent.controller.collapsedSections = {};
            spotlightContent.controller.selectedFlatIndex = 0;
            spotlightContent.controller.selectedItem = null;
            spotlightContent.controller.historyIndex = -1;
            spotlightContent.controller.searchQuery = targetQuery;

            spotlightContent.controller.performSearch();
        }
        if (spotlightContent.resetScroll) {
            spotlightContent.resetScroll();
        }
        if (spotlightContent.actionPanel) {
            spotlightContent.actionPanel.hide();
        }
    }

    function _finishShow(query, mode) {
        spotlightOpen = true;
        isClosing = false;
        openedFromOverview = false;

        keyboardActive = true;
        ModalManager.openModal(root);
        if (useHyprlandFocusGrab)
            focusGrab.active = true;

        _ensureContentLoadedAndInitialize(query || "", mode || "");
    }

    function show() {
        closeCleanupTimer.stop();

        var focusedScreen = CompositorService.getFocusedScreen();
        if (focusedScreen && launcherWindow.screen !== focusedScreen) {
            spotlightOpen = false;
            isClosing = false;
            launcherWindow.screen = focusedScreen;
            Qt.callLater(() => root._finishShow("", ""));
            return;
        }

        _finishShow("", "");
    }

    function showWithQuery(query) {
        closeCleanupTimer.stop();

        var focusedScreen = CompositorService.getFocusedScreen();
        if (focusedScreen && launcherWindow.screen !== focusedScreen) {
            spotlightOpen = false;
            isClosing = false;
            launcherWindow.screen = focusedScreen;
            Qt.callLater(() => root._finishShow(query, ""));
            return;
        }

        _finishShow(query, "");
    }

    function hide() {
        if (!spotlightOpen)
            return;
        openedFromOverview = false;
        isClosing = true;
        contentVisible = false;

        keyboardActive = false;
        spotlightOpen = false;
        focusGrab.active = false;
        ModalManager.closeModal(root);

        closeCleanupTimer.start();
    }

    function toggle() {
        spotlightOpen ? hide() : show();
    }

    function showWithMode(mode) {
        closeCleanupTimer.stop();

        var focusedScreen = CompositorService.getFocusedScreen();
        if (focusedScreen && launcherWindow.screen !== focusedScreen) {
            spotlightOpen = false;
            isClosing = false;
            launcherWindow.screen = focusedScreen;
            Qt.callLater(() => root._finishShow("", mode));
            return;
        }

        spotlightOpen = true;
        isClosing = false;
        openedFromOverview = false;

        keyboardActive = true;
        ModalManager.openModal(root);
        if (useHyprlandFocusGrab)
            focusGrab.active = true;

        _ensureContentLoadedAndInitialize("", mode);
    }

    function toggleWithMode(mode) {
        if (spotlightOpen) {
            hide();
        } else {
            showWithMode(mode);
        }
    }

    function toggleWithQuery(query) {
        if (spotlightOpen) {
            hide();
        } else {
            showWithQuery(query);
        }
    }

    Timer {
        id: closeCleanupTimer
        interval: Theme.modalAnimationDuration + 50
        repeat: false
        onTriggered: {
            isClosing = false;
            if (root.unloadContentOnClose)
                launcherContentLoader.active = false;
            dialogClosed();
        }
    }

    Connections {
        target: spotlightContent?.controller ?? null

        function onModeChanged(mode) {
            if (spotlightContent.controller.autoSwitchedToFiles)
                return;
            SessionData.setLauncherLastMode(mode);
        }
    }

    HyprlandFocusGrab {
        id: focusGrab
        windows: [launcherWindow]
        active: false

        onCleared: {
            if (spotlightOpen) {
                hide();
            }
        }
    }

    Connections {
        target: ModalManager
        function onCloseAllModalsExcept(excludedModal) {
            if (excludedModal !== root && spotlightOpen) {
                hide();
            }
        }
    }

    Connections {
        target: Quickshell
        function onScreensChanged() {
            if (Quickshell.screens.length === 0)
                return;

            const screenName = launcherWindow.screen?.name;
            if (screenName) {
                for (let i = 0; i < Quickshell.screens.length; i++) {
                    if (Quickshell.screens[i].name === screenName)
                        return;
                }
            }

            if (spotlightOpen)
                hide();

            const newScreen = CompositorService.getFocusedScreen() ?? Quickshell.screens[0];
            if (newScreen)
                launcherWindow.screen = newScreen;
        }
    }

    PanelWindow {
        id: launcherWindow
        visible: spotlightOpen || isClosing
        color: "transparent"
        exclusionMode: ExclusionMode.Ignore

        WindowBlur {
            targetWindow: launcherWindow
            readonly property real s: Math.min(1, modalContainer.scale)
            blurX: root.modalX + root.modalWidth * (1 - s) * 0.5
            blurY: root.modalY + root.modalHeight * (1 - s) * 0.5
            blurWidth: (contentVisible && modalContainer.opacity > 0) ? root.modalWidth * s : 0
            blurHeight: (contentVisible && modalContainer.opacity > 0) ? root.modalHeight * s : 0
            blurRadius: root.cornerRadius
        }

        WlrLayershell.namespace: "dms:spotlight"
        WlrLayershell.layer: {
            switch (Quickshell.env("DMS_MODAL_LAYER")) {
            case "bottom":
                console.error("DankModal: 'bottom' layer is not valid for modals. Defaulting to 'top' layer.");
                return WlrLayershell.Top;
            case "background":
                console.error("DankModal: 'background' layer is not valid for modals. Defaulting to 'top' layer.");
                return WlrLayershell.Top;
            case "overlay":
                return WlrLayershell.Overlay;
            default:
                return WlrLayershell.Top;
            }
        }
        WlrLayershell.keyboardFocus: keyboardActive ? (root.useHyprlandFocusGrab ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive) : WlrKeyboardFocus.None

        anchors {
            top: true
            bottom: true
            left: true
            right: true
        }

        mask: Region {
            item: spotlightOpen ? fullScreenMask : null
        }

        Item {
            id: fullScreenMask
            anchors.fill: parent
        }

        Rectangle {
            id: backgroundDarken
            anchors.fill: parent
            color: "black"
            opacity: contentVisible && SettingsData.modalDarkenBackground ? 0.5 : 0
            visible: contentVisible || opacity > 0

            Behavior on opacity {
                DankAnim {
                    duration: Theme.modalAnimationDuration
                    easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
                }
            }
        }

        MouseArea {
            anchors.fill: parent
            enabled: spotlightOpen
            onClicked: mouse => {
                var contentX = modalContainer.x;
                var contentY = modalContainer.y;
                var contentW = modalContainer.width;
                var contentH = modalContainer.height;

                if (mouse.x < contentX || mouse.x > contentX + contentW || mouse.y < contentY || mouse.y > contentY + contentH) {
                    root.hide();
                }
            }
        }

        Item {
            id: modalContainer
            x: root.modalX
            y: root.modalY
            width: root.modalWidth
            height: root.modalHeight
            visible: contentVisible || opacity > 0

            opacity: contentVisible ? 1 : 0
            scale: contentVisible ? 1 : 0.96
            transformOrigin: Item.Center

            Behavior on opacity {
                DankAnim {
                    duration: Theme.modalAnimationDuration
                    easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
                }
            }

            Behavior on scale {
                DankAnim {
                    duration: Theme.modalAnimationDuration
                    easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
                }
            }

            ElevationShadow {
                id: launcherShadowLayer
                anchors.fill: parent
                level: Theme.elevationLevel3
                fallbackOffset: 6
                targetColor: root.backgroundColor
                borderColor: root.borderColor
                borderWidth: root.borderWidth
                targetRadius: root.cornerRadius
                shadowEnabled: Theme.elevationEnabled && SettingsData.modalElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
            }

            MouseArea {
                anchors.fill: parent
                onPressed: mouse => mouse.accepted = true
            }

            FocusScope {
                anchors.fill: parent
                focus: keyboardActive

                Loader {
                    id: launcherContentLoader
                    anchors.fill: parent
                    active: !root.unloadContentOnClose || root.spotlightOpen || root.isClosing || root.contentVisible || root._pendingInitialize
                    asynchronous: false
                    sourceComponent: LauncherContent {
                        focus: true
                        parentModal: root
                    }

                    onLoaded: {
                        if (root._pendingInitialize) {
                            root._initializeAndShow(root._pendingQuery, root._pendingMode);
                            root._pendingInitialize = false;
                        }
                    }
                }

                Keys.onEscapePressed: event => {
                    root.hide();
                    event.accepted = true;
                }
            }

            Rectangle {
                anchors.fill: parent
                radius: root.cornerRadius
                color: "transparent"
                border.color: BlurService.borderColor
                border.width: BlurService.borderWidth
            }
        }
    }
}
