import QtQuick
import Qt.labs.folderlistmodel
import Quickshell
import Quickshell.Bluetooth
import Quickshell.Io
import Quickshell.Services.Pipewire
import "../.."

Item {
    id: root
    width: parent ? parent.width : 1280
    height: parent ? parent.height : 820
    focus: true

    /* ------------------------------
       PIXEL CONSTANTS (DO NOT TOUCH)
       ------------------------------ */

    property int menuLeft: 64
    property int menuTop: 140
    property int lineHeight: 38 + 40 + 1
    property int visibleRows: Math.max(1, Math.floor((height - menuTop - 64) / lineHeight))
    property int scrollOffset: 0

    property int nameFontSize: 32
    property int stateFontSize: 28

    property int stateColumnX: 824

    property int soulOffsetX: -36 - 32
    property int soulOffsetY: -26

    /* ------------------------------ */

    property ShellStateManager manager: null
    property int activeSelection: 0
    property bool inBluetoothMenu: false
    property bool inWallpaperMenu: false
    property bool inShellMenu: false
    property bool inPowerMenu: false
    property bool inPowerConfirm: false

    property bool isSelected: false

    property string wallpapersDir: (Quickshell.env("HOME") || "") + "/Pictures/Wallpapers"
    property string wallpaperCachePath: (Quickshell.env("HOME") || "") + "/.cache/.wallpaper"
    property string currentWallpaperPath: ""

    function clamp(v, lo, hi) {
        return Math.max(lo, Math.min(hi, v));
    }

    function menuLength() {
        if (root.inBluetoothMenu && bluetoothRepeater)
            return bluetoothRepeater.count;
        if (root.inWallpaperMenu && wallpaperFolderModel)
            return wallpaperFolderModel.count;
        if (!menuModel)
            return 0;
        if (typeof menuModel.count === "function")
            return menuModel.count();
        if (menuModel.count !== undefined)
            return menuModel.count;
        if (menuModel.length !== undefined)
            return menuModel.length;
        return 0;
    }

    function menuAt(index) {
        if (!menuModel)
            return null;
        if (menuModel.get)
            return menuModel.get(index);
        if (menuModel.length !== undefined)
            return menuModel[index];
        return null;
    }

    function wrapIndex(i) {
        const length = menuLength();
        if (length === 0)
            return 0;
        return (i + length) % length;
    }

    function currentAction() {
        if (root.inBluetoothMenu || root.inWallpaperMenu || root.inShellMenu || root.inPowerMenu)
            return null;
        return menuLength() > 0 ? menuAt(activeSelection) : null;
    }

    function clampSelection() {
        const length = menuLength();
        if (length === 0) {
            activeSelection = 0;
            scrollOffset = 0;
            return;
        }
        activeSelection = clamp(activeSelection, 0, length - 1);
        const maxOffset = Math.max(0, length - visibleRows);
        scrollOffset = clamp(scrollOffset, 0, maxOffset);
    }

    function ensureVisible() {
        if (!root.inWallpaperMenu)
            return;
        const length = menuLength();
        if (length === 0) {
            scrollOffset = 0;
            return;
        }
        if (activeSelection < scrollOffset)
            scrollOffset = activeSelection;
        else if (activeSelection >= scrollOffset + visibleRows)
            scrollOffset = Math.max(0, activeSelection - visibleRows + 1);
    }

    function bluetoothDisplayName(device) {
        if (!device)
            return "";
        if (device.name && device.name.length > 0)
            return device.name;
        return device.deviceName || "";
    }

    function bluetoothDisplayState(device) {
        if (!device)
            return "";
        // dont change symbols
        return device.connected ? "✓" : "";
    }

    function bluetoothDeviceAt(index) {
        const item = bluetoothRepeater.itemAt(index);
        if (!item)
            return null;
        return item.device || null;
    }

    function trimText(text) {
        return (text || "").replace(/^\s+|\s+$/g, "");
    }

    function normalizedPath(path) {
        var value = trimText(path);
        if (value.indexOf("file://") === 0)
            value = value.slice(7);
        return value;
    }

    function wallpaperNameAt(index) {
        if (!wallpaperFolderModel || index < 0 || index >= wallpaperFolderModel.count)
            return "";
        var name = wallpaperFolderModel.get(index, "fileName") || "";
        return name.replace(/\.[^/.]+$/, "");
    }

    function wallpaperPathAt(index) {
        if (!wallpaperFolderModel || index < 0 || index >= wallpaperFolderModel.count)
            return "";
        return wallpaperFolderModel.get(index, "filePath") || "";
    }

    function currentWallpaperIndex() {
        var current = normalizedPath(currentWallpaperPath);
        if (!current || !wallpaperFolderModel)
            return -1;
        for (var i = 0; i < wallpaperFolderModel.count; i++) {
            if (normalizedPath(wallpaperPathAt(i)) === current)
                return i;
        }
        return -1;
    }

    function refreshCurrentWallpaper() {
        root.currentWallpaperPath = normalizedPath(wallpaperFile.text());
    }

    function applyWallpaper(path) {
        var normalized = normalizedPath(path);
        if (!normalized || normalized.length === 0)
            return;

        root.currentWallpaperPath = normalized;
        wallpaperFile.setText(normalized + "\n");

        wallpaperApplyProcess.running = false;
        wallpaperApplyProcess.environment = {
            "WALLPAPER_PATH": normalized
        };
        wallpaperApplyProcess.command = ["bash", "-lc", "rm -rf \"$HOME/.cache/wal\"; if [[ \"$(hostname)\" != \"gentoo\" ]]; then swww img \"$WALLPAPER_PATH\" --transition-type none; else HYPRPAPER_PID=\"$(pidof hyprpaper)\"; if [ ${#HYPRPAPER_PID} -lt 1 ]; then hyprctl dispatch exec hyprpaper; sleep 1; fi; hyprctl hyprpaper unload all; hyprctl hyprpaper preload \"$WALLPAPER_PATH\"; hyprctl hyprpaper wallpaper ,\"$WALLPAPER_PATH\"; fi"];
        wallpaperApplyProcess.running = true;
    }

    PwObjectTracker {
        objects: [Pipewire.defaultAudioSink]
    }

    property int bluetoothActionIndex: 1
    property int wallpaperActionIndex: 2
    property int shellActionIndex: 3
    property int powerActionIndex: 4
    property int pendingPowerActionIndex: 0
    property var pendingPowerCommand: []
    property var actions: [
        {
            name: "Master Volume",
            arr: function (dir) {
                const sink = Pipewire.defaultAudioSink;
                if (!sink || !sink.audio)
                    return;
                const step = 0.05;
                sink.audio.muted = false;
                sink.audio.volume = clamp(sink.audio.volume + dir * step, 0, 1);
            },
            getState: function () {
                const sink = Pipewire.defaultAudioSink;
                if (!sink || !sink.audio)
                    return "—";
                return Math.round(sink.audio.volume * 100) + "%";
            }
        },
        {
            name: "Bluetooth",
            ent: function () {
                root.inBluetoothMenu = true;
                root.inWallpaperMenu = false;
                root.inShellMenu = false;
                root.isSelected = false;
                root.activeSelection = 0;
                root.clampSelection();
            },
            getState: function () {
                return "";
            }
        },
        {
            name: "Wallpaper",
            ent: function () {
                root.inWallpaperMenu = true;
                root.inBluetoothMenu = false;
                root.inShellMenu = false;
                root.isSelected = false;
                var currentIndex = root.currentWallpaperIndex();
                root.activeSelection = currentIndex >= 0 ? currentIndex : 0;
                root.scrollOffset = 0;
                root.clampSelection();
                root.ensureVisible();
            },
            getState: function () {
                return "";
            }
        },
        {
            name: "Shell",
            ent: function () {
                root.inShellMenu = true;
                root.inBluetoothMenu = false;
                root.inWallpaperMenu = false;
                root.inPowerMenu = false;
                root.inPowerConfirm = false;
                root.isSelected = false;
                root.activeSelection = 0;
                root.clampSelection();
            },
            getState: function () {
                return "";
            }
        },
        {
            name: "Power",
            ent: function () {
                root.inPowerMenu = true;
                root.inPowerConfirm = false;
                root.inBluetoothMenu = false;
                root.inWallpaperMenu = false;
                root.inShellMenu = false;
                root.isSelected = false;
                root.activeSelection = 0;
                root.pendingPowerActionIndex = 0;
                root.pendingPowerCommand = [];
                root.clampSelection();
            },
            getState: function () {
                return "";
            }
        }
    ]

    property var powerActions: [
        {
            name: "Sleep",
            command: ["systemctl", "suspend"]
        },
        {
            name: "Shutdown",
            command: ["systemctl", "poweroff"]
        },
        {
            name: "Reboot",
            command: ["systemctl", "reboot"]
        },
        {
            name: "Logout",
            command: ["hyprctl", "dispatch", "exit"]
        }
    ]

    property var powerConfirmActions: [
        {
            name: "Yes"
        },
        {
            name: "No"
        }
    ]

    property var shellActions: [
        {
            name: "Stack Preview",
            ent: function () {
                if (manager && manager.toggleNotificationStackPreviewEnabled)
                    manager.toggleNotificationStackPreviewEnabled();
            },
            getState: function () {
                if (!manager || !manager.notificationStackPreviewEnabled)
                    return "ON";
                return manager.notificationStackPreviewEnabled() ? "ON" : "OFF";
            }
        },
        {
            name: "Media Overlay",
            ent: function () {
                if (manager && manager.toggleMprisOverlayEnabled)
                    manager.toggleMprisOverlayEnabled();
            },
            getState: function () {
                if (!manager || !manager.mprisOverlayEnabled)
                    return "ON";
                return manager.mprisOverlayEnabled() ? "ON" : "OFF";
            }
        }
    ]

    property var menuModel: root.inBluetoothMenu ? Bluetooth.devices : (root.inWallpaperMenu ? wallpaperFolderModel : (root.inShellMenu ? shellActions : (root.inPowerMenu ? (root.inPowerConfirm ? powerConfirmActions : powerActions) : actions)))

    FolderListModel {
        id: wallpaperFolderModel
        folder: "file://" + root.wallpapersDir
        nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.webp", "*.bmp", "*.gif"]
        showDirs: false
        showDotAndDotDot: false
        sortField: FolderListModel.Name
        sortReversed: false
        onCountChanged: {
            if (root.inWallpaperMenu) {
                root.clampSelection();
                root.ensureVisible();
            }
        }
    }

    FileView {
        id: wallpaperFile
        path: root.wallpaperCachePath
        watchChanges: true
        onLoaded: root.refreshCurrentWallpaper()
        onFileChanged: reload()
        onLoadFailed: root.currentWallpaperPath = ""
    }

    Process {
        id: wallpaperApplyProcess
    }

    Process {
        id: powerCommandProcess
    }

    function executePowerCommand(command) {
        if (!command || command.length === 0)
            return;
        powerCommandProcess.running = false;
        powerCommandProcess.command = command;
        powerCommandProcess.running = true;
        if (manager && manager.closeShell)
            manager.closeShell();
    }

    function pendingPowerActionName() {
        if (pendingPowerActionIndex < 0 || pendingPowerActionIndex >= powerActions.length)
            return "";
        var action = powerActions[pendingPowerActionIndex];
        return action && action.name ? String(action.name) : "";
    }

    Connections {
        target: Bluetooth.devices
        ignoreUnknownSignals: true
        function onCountChanged() {
            if (root.inBluetoothMenu)
                root.clampSelection();
        }
        function onModelReset() {
            if (root.inBluetoothMenu)
                root.clampSelection();
        }
        function onRowsInserted() {
            if (root.inBluetoothMenu)
                root.clampSelection();
        }
        function onRowsRemoved() {
            if (root.inBluetoothMenu)
                root.clampSelection();
        }
    }

    Connections {
        target: wallpaperFolderModel
        ignoreUnknownSignals: true
        function onModelReset() {
            if (root.inWallpaperMenu) {
                root.clampSelection();
                root.ensureVisible();
            }
        }
        function onRowsInserted() {
            if (root.inWallpaperMenu) {
                root.clampSelection();
                root.ensureVisible();
            }
        }
        function onRowsRemoved() {
            if (root.inWallpaperMenu) {
                root.clampSelection();
                root.ensureVisible();
            }
        }
    }

    Text {
        text: root.inPowerConfirm ? "CONFIRM" : (root.inPowerMenu ? "POWER" : (root.inBluetoothMenu ? "BLUETOOTH" : (root.inWallpaperMenu ? "WALLPAPER" : (root.inShellMenu ? "SHELL" : "CONFIG"))))
        font.family: "8bitoperator JVE"
        font.pixelSize: 71
        renderType: Text.NativeRendering
        font.hintingPreference: Font.PreferNoHinting
        smooth: false
        antialiasing: false
        anchors.horizontalCenter: parent.horizontalCenter
        color: "#ffffff"
        y: 32
    }

    Text {
        visible: root.inPowerConfirm
        text: root.pendingPowerActionName().toUpperCase() + "?"
        font.family: "8bitoperator JVE"
        font.pixelSize: 44
        renderType: Text.NativeRendering
        font.hintingPreference: Font.PreferNoHinting
        smooth: false
        antialiasing: false
        anchors.horizontalCenter: parent.horizontalCenter
        color: "#fefe00"
        y: 102
    }

    Repeater {
        id: bluetoothRepeater
        model: root.menuModel

        delegate: Item {
            width: root.width
            height: lineHeight
            x: 0
            y: menuTop + (root.inWallpaperMenu ? (index - root.scrollOffset) * lineHeight : index * lineHeight)
            visible: !root.inWallpaperMenu || (index >= root.scrollOffset && index < root.scrollOffset + root.visibleRows)

            property var device: root.inBluetoothMenu ? modelData : null

            Image {
                source: "./soul.png"
                width: 36
                height: 36
                x: 182
                y: 8 + 14
                visible: root.activeSelection == index
            }

            Text {
                x: 239
                y: 0
                text: root.inBluetoothMenu ? root.bluetoothDisplayName(modelData) : (root.inWallpaperMenu ? root.wallpaperNameAt(index) : modelData.name)
                width: root.width - 239 - (root.inWallpaperMenu ? 96 : 300)
                font.family: "8bitoperator JVE"
                font.pixelSize: 71
                font.letterSpacing: 1
                renderType: Text.NativeRendering
                font.hintingPreference: Font.PreferNoHinting
                smooth: false
                antialiasing: false
                wrapMode: Text.NoWrap
                elide: Text.ElideRight
                color: (root.activeSelection == index && (root.isSelected == true || root.inBluetoothMenu || root.inWallpaperMenu || root.inPowerMenu)) ? "#fefe00" : "#ffffff"
            }

            // Option state
            Text {
                x: menuLeft + stateColumnX
                y: 4
                visible: !root.inWallpaperMenu
                text: root.inBluetoothMenu ? root.bluetoothDisplayState(modelData) : (modelData.getState ? modelData.getState() : "")
                font.family: "8bitoperator JVE"
                font.pixelSize: 71
                font.letterSpacing: 1
                renderType: Text.NativeRendering
                font.hintingPreference: Font.PreferNoHinting
                smooth: false
                antialiasing: false
                color: (root.activeSelection == index && (root.isSelected == true || root.inBluetoothMenu || root.inWallpaperMenu || root.inPowerMenu)) ? "#fefe00" : "#ffffff"
            }
        }
    }

    /* ------------------------------
       INPUT HANDLING
       ------------------------------ */

    function handleKey(key) {
        switch (key) {
        case Qt.Key_Up:
            if (root.inBluetoothMenu || root.inWallpaperMenu || root.inPowerMenu || root.isSelected === false) {
                activeSelection = wrapIndex(activeSelection - 1);
                root.ensureVisible();
            }
            return true;
        case Qt.Key_Down:
            if (root.inBluetoothMenu || root.inWallpaperMenu || root.inPowerMenu || root.isSelected === false) {
                activeSelection = wrapIndex(activeSelection + 1);
                root.ensureVisible();
            }
            return true;
        case Qt.Key_Left:
            {
                const a = currentAction();
                if (a && a.arr && root.isSelected === true)
                    a.arr(-1);
                return true;
            }
        case Qt.Key_Right:
            {
                const a = currentAction();
                if (a && a.arr && root.isSelected === true)
                    a.arr(1);
                return true;
            }
        case Qt.Key_Z:
        case Qt.Key_Return:
        case Qt.Key_Enter:
            {
                if (root.inBluetoothMenu) {
                    const device = bluetoothDeviceAt(activeSelection);
                    console.log(root.inBluetoothMenu, activeSelection, device);
                    if (device) {
                        if (!device.connected) {
                            device.connect();
                        } else {
                            device.disconnect();
                        }
                        // device.connected = !device.connected;
                    }
                } else if (root.inWallpaperMenu) {
                    const wallpaperPath = wallpaperPathAt(activeSelection);
                    if (wallpaperPath && wallpaperPath.length > 0)
                        root.applyWallpaper(wallpaperPath);
                } else if (root.inShellMenu) {
                    const shellAction = menuAt(activeSelection);
                    if (shellAction && shellAction.ent)
                        shellAction.ent();
                } else if (root.inPowerConfirm) {
                    const confirmAction = menuAt(activeSelection);
                    if (confirmAction && confirmAction.name === "Yes") {
                        root.executePowerCommand(root.pendingPowerCommand);
                    } else {
                        root.inPowerConfirm = false;
                        root.activeSelection = root.pendingPowerActionIndex;
                        root.clampSelection();
                    }
                } else if (root.inPowerMenu) {
                    const powerAction = menuAt(activeSelection);
                    if (powerAction && powerAction.command) {
                        root.pendingPowerActionIndex = activeSelection;
                        root.pendingPowerCommand = powerAction.command;
                        root.inPowerConfirm = true;
                        root.activeSelection = 0;
                        root.clampSelection();
                    }
                } else {
                    const a = currentAction();
                    if (a && a.ent) {
                        a.ent();
                    } else {
                        root.isSelected = !root.isSelected;
                    }
                }
                return true;
            }
        case Qt.Key_X:
        case Qt.Key_Shift:
        case Qt.Key_Escape:
            if (root.inWallpaperMenu) {
                root.inWallpaperMenu = false;
                root.isSelected = false;
                root.scrollOffset = 0;
                root.activeSelection = root.wallpaperActionIndex;
                root.clampSelection();
            } else if (root.inPowerConfirm) {
                root.inPowerConfirm = false;
                root.isSelected = false;
                root.activeSelection = root.pendingPowerActionIndex;
                root.clampSelection();
            } else if (root.inPowerMenu) {
                root.inPowerMenu = false;
                root.inPowerConfirm = false;
                root.isSelected = false;
                root.pendingPowerActionIndex = 0;
                root.pendingPowerCommand = [];
                root.activeSelection = root.powerActionIndex;
                root.clampSelection();
            } else if (root.inShellMenu) {
                root.inShellMenu = false;
                root.isSelected = false;
                root.activeSelection = root.shellActionIndex;
                root.clampSelection();
            } else if (root.inBluetoothMenu) {
                root.inBluetoothMenu = false;
                root.isSelected = false;
                root.activeSelection = root.bluetoothActionIndex;
                root.clampSelection();
            } else if (root.isSelected === true) {
                root.isSelected = false;
            } else {
                if (manager && manager.closeQuickSettings) {
                    manager.closeQuickSettings();
                }
            }
            return true;
        }
        return false;
    }

    Component.onCompleted: {
        root.activeSelection = 0;
        root.isSelected = false;
        root.inBluetoothMenu = false;
        root.inWallpaperMenu = false;
        root.inShellMenu = false;
        root.inPowerMenu = false;
        root.inPowerConfirm = false;
        root.pendingPowerActionIndex = 0;
        root.pendingPowerCommand = [];
        root.scrollOffset = 0;
        root.refreshCurrentWallpaper();
        ShellInputManager.registerHandler("quickSettings", handleKey);
    }

    Component.onDestruction: {
        ShellInputManager.unregisterHandler("quickSettings");
    }
}
