pragma Singleton

// Freedesktop default handlers and session autostart entries.
//
// The helper owns parsing and atomic desktop-file writes. This singleton keeps
// the QML side typed and reactive, and every external command crosses Process
// as an argument array.

import Quickshell
import Quickshell.Io
import QtQuick

Singleton {
    id: root

    property var handlers: ({})
    property var autostartEntries: []
    property var luaAutostartEntries: []
    property string lastError: ""

    readonly property bool busy: snapshotProcess.running || mutationProcess.running
    readonly property string helper: Quickshell.shellDir + "/scripts/panama-default-apps"
    readonly property var supportedRoles: ["browser", "mail", "files", "terminal", "music", "images", "video"]

    Process {
        id: snapshotProcess

        stdout: StdioCollector {
            onStreamFinished: root.applySnapshot(this.text)
        }
        onExited: (exitCode, exitStatus) => {
            if (exitCode !== 0)
                root.lastError = "Default applications could not be read. Try refreshing."
        }
    }

    Process {
        id: mutationProcess

        onExited: (exitCode, exitStatus) => {
            if (exitCode !== 0) {
                root.lastError = "That application setting could not be changed."
                return;
            }
            root.refresh();
        }
    }

    function applySnapshot(text: string): void {
        try {
            const payload = JSON.parse(text);
            root.handlers = payload.handlers ?? ({});
            root.autostartEntries = payload.autostartEntries ?? [];
            root.luaAutostartEntries = payload.luaAutostartEntries ?? [];
            root.lastError = "";
        } catch (error) {
            root.lastError = "Default applications returned an unreadable response."
        }
    }

    function refresh(): void {
        if (root.busy)
            return;
        root.lastError = "";
        snapshotProcess.exec([root.helper, "snapshot"]);
    }

    function knownDesktopId(desktopId: string): bool {
        if (!/^[A-Za-z0-9][A-Za-z0-9._+-]*\.desktop$/.test(desktopId))
            return false;
        const entries = DesktopEntries.applications.values;
        return entries.some(entry => {
            const entryId = String(entry.id ?? "");
            return entryId === desktopId || entryId + ".desktop" === desktopId;
        });
    }

    function setDefault(role: string, desktopId: string): void {
        if (root.busy)
            return;
        if (!root.supportedRoles.includes(role) || !root.knownDesktopId(desktopId)) {
            root.lastError = "Choose an application from the available list."
            return;
        }
        root.lastError = "";
        mutationProcess.exec([root.helper, "set-default", role, desktopId]);
    }

    function setAutostart(desktopId: string, enabled: bool): void {
        if (root.busy)
            return;
        const known = root.autostartEntries.some(entry => entry.id === desktopId);
        if (!known) {
            root.lastError = "That user autostart entry is no longer available."
            return;
        }
        root.lastError = "";
        mutationProcess.exec([root.helper, "set-autostart", desktopId, String(enabled)]);
    }

    Component.onCompleted: root.refresh()
}
