pragma Singleton

// Generated lock-screen state. Visual preferences are coalesced into one
// helper invocation, while the last valid status remains visible if a helper
// response is malformed.

import Quickshell
import Quickshell.Io
import QtQuick

import qs.config

Singleton {
    id: root

    readonly property string helperPath: Quickshell.shellDir + "/scripts/panama-lock"

    property bool generated: false
    property string path: ""
    property bool fallback: true
    property string lastError: ""
    property string watchedSignature: ""
    property bool regenerateAfterCurrent: false

    readonly property bool busy: generateProcess.running || statusProcess.running

    function preferenceSignature(): string {
        DesktopPreferences.revision;
        return JSON.stringify([
            DesktopPreferences.get("lockBackgroundMode"),
            DesktopPreferences.get("lockBlurLevel"),
            DesktopPreferences.get("lockShowClock"),
            DesktopPreferences.get("lockShowDate"),
            DesktopPreferences.get("lockShowUser"),
            DesktopPreferences.get("lockFadeOnEmpty"),
            DesktopPreferences.get("use24Hour"),
            DesktopPreferences.get("colorScheme"),
            DesktopPreferences.get("wallpaperPath"),
            DesktopPreferences.get("wallpaperMode"),
            DesktopPreferences.get("wallpaperPerMonitor")
        ]);
    }

    function applyStatus(text: string): void {
        try {
            const state = JSON.parse(text);
            if (!state || typeof state.generated !== "boolean"
                    || typeof state.path !== "string" || state.path.length === 0)
                throw new Error("invalid lock status");
            root.generated = state.generated;
            root.path = state.path;
            root.fallback = state.fallback === true;
            root.lastError = typeof state.error === "string" ? state.error : "";
        } catch (error) {
            root.lastError = "The lock-screen configuration could not be read.";
        }
    }

    function refresh(): void {
        if (!statusProcess.running)
            statusProcess.exec([root.helperPath, "status"]);
    }

    function regenerate(): void {
        if (generateProcess.running) {
            root.regenerateAfterCurrent = true;
            return;
        }
        generateProcess.exec([root.helperPath, "generate"]);
    }

    Process {
        id: statusProcess

        property bool parsed: false

        onRunningChanged: {
            if (running)
                parsed = false;
        }

        stdout: StdioCollector {
            onStreamFinished: {
                statusProcess.parsed = true;
                root.applyStatus(this.text);
            }
        }

        onExited: (exitCode, exitStatus) => {
            if (exitCode !== 0 && !statusProcess.parsed)
                root.lastError = "The lock-screen configuration could not be read.";
        }
    }

    Process {
        id: generateProcess

        onExited: (exitCode, exitStatus) => {
            if (exitCode !== 0)
                root.lastError = "The lock-screen configuration could not be generated.";
            root.refresh();
            if (root.regenerateAfterCurrent) {
                root.regenerateAfterCurrent = false;
                regenerateTimer.restart();
            }
        }
    }

    Connections {
        target: DesktopPreferences

        function onRevisionChanged(): void {
            const signature = root.preferenceSignature();
            if (signature === root.watchedSignature)
                return;
            root.watchedSignature = signature;
            regenerateTimer.restart();
        }
    }

    Timer {
        id: regenerateTimer
        interval: 250
        onTriggered: root.regenerate()
    }

    Component.onCompleted: {
        root.watchedSignature = root.preferenceSignature();
        root.refresh();
        regenerateTimer.restart();
    }
}
