import QtQuick
import Quickshell
import Quickshell.Io
import qs.Utils
pragma Singleton

Singleton {
    id: root

    property bool isInhibited: false
    property string reason: "User requested"
    property var activeInhibitors: []
    property var timeout: null // in seconds
    // True when the native Wayland IdleInhibitor is handling inhibition
    // (set by the IdleInhibitor element in MainScreen via the nativeInhibitor property)
    property bool nativeInhibitorAvailable: false

    function init() {
        Logger.i("IdleInhibitor", "Service started");
    }

    // Add an inhibitor
    function addInhibitor(id, reason = "Application request") {
        if (activeInhibitors.includes(id)) {
            Logger.w("IdleInhibitor", "Inhibitor already active:", id);
            return false;
        }
        activeInhibitors.push(id);
        updateInhibition(reason);
        Logger.d("IdleInhibitor", "Added inhibitor:", id);
        return true;
    }

    // Remove an inhibitor
    function removeInhibitor(id) {
        const index = activeInhibitors.indexOf(id);
        if (index === -1) {
            Logger.w("IdleInhibitor", "Inhibitor not found:", id);
            return false;
        }
        activeInhibitors.splice(index, 1);
        updateInhibition();
        Logger.d("IdleInhibitor", "Removed inhibitor:", id);
        return true;
    }

    // Update the actual system inhibition
    function updateInhibition(newReason = reason) {
        const shouldInhibit = activeInhibitors.length > 0;
        if (shouldInhibit === isInhibited)
            return ;

        if (shouldInhibit)
            startInhibition(newReason);
        else
            stopInhibition();
    }

    // Start system inhibition
    function startInhibition(newReason) {
        reason = newReason;
        if (nativeInhibitorAvailable)
            Logger.d("IdleInhibitor", "Native inhibitor active");
        else
            startSubprocessInhibition();
        isInhibited = true;
        Logger.i("IdleInhibitor", "Started inhibition:", reason);
    }

    // Stop system inhibition
    function stopInhibition() {
        if (!isInhibited)
            return ;

        if (!nativeInhibitorAvailable && inhibitorProcess.running)
            inhibitorProcess.signal(15);

        // SIGTERM
        isInhibited = false;
        Logger.i("IdleInhibitor", "Stopped inhibition");
    }

    // Subprocess fallback using systemd-inhibit
    function startSubprocessInhibition() {
        inhibitorProcess.command = ["systemd-inhibit", "--what=idle", "--why=" + reason, "--mode=block", "sleep", "infinity"];
        inhibitorProcess.running = true;
    }

    // Manual toggle for user control
    function manualToggle() {
        // clear any existing timeout
        timeout = null;
        if (activeInhibitors.includes("manual")) {
            removeManualInhibitor();
            return false;
        } else {
            addManualInhibitor(null);
            return true;
        }
    }

    function changeTimeout(delta) {
        if (timeout == null && delta < 0)
            return ;

        if (timeout == null && delta > 0) {
            // enable manual inhibitor and set timeout
            addManualInhibitor(timeout + delta);
            return ;
        }
        if (timeout + delta <= 0) {
            // disable manual inhibitor
            removeManualInhibitor();
            return ;
        }
        if (timeout + delta > 0) {
            // change timeout
            addManualInhibitor(timeout + delta);
            return ;
        }
    }

    function removeManualInhibitor() {
        if (timeout !== null) {
            timeout = null;
            if (inhibitorTimeout.running)
                inhibitorTimeout.stop();

        }
        if (activeInhibitors.includes("manual")) {
            removeInhibitor("manual");
            Logger.i("IdleInhibitor", "Manual inhibition disabled");
        }
    }

    function addManualInhibitor(timeoutSec) {
        if (!activeInhibitors.includes("manual"))
            addInhibitor("manual", "Manually activated by user");

        if (timeoutSec === null && timeout === null) {
            Logger.i("IdleInhibitor", "Manual inhibition enabled");
            return ;
        } else if (timeoutSec !== null && timeout === null) {
            timeout = timeoutSec;
            inhibitorTimeout.start();
            Logger.i("IdleInhibitor", "Manual inhibition enabled with timeout:", timeoutSec);
            return ;
        } else if (timeoutSec !== null && timeout !== null) {
            timeout = timeoutSec;
            Logger.i("IdleInhibitor", "Manual inhibition timeout changed to:", timeoutSec);
            return ;
        } else if (timeoutSec === null && timeout !== null) {
            timeout = null;
            inhibitorTimeout.stop();
            Logger.i("IdleInhibitor", "Manual inhibition timeout cleared");
            return ;
        }
    }

    // Clean up on shutdown
    Component.onDestruction: {
        stopInhibition();
    }

    // Process for maintaining the inhibition (subprocess fallback only)
    Process {
        id: inhibitorProcess

        running: false
        onExited: function(exitCode, exitStatus) {
            if (isInhibited) {
                Logger.w("IdleInhibitor", "Inhibitor process exited unexpectedly:", exitCode);
                isInhibited = false;
            }
        }
        onStarted: function() {
            Logger.d("IdleInhibitor", "Inhibitor process started successfully");
        }
    }

    Timer {
        id: inhibitorTimeout

        repeat: true
        interval: 1000 // 1 second
        onTriggered: function() {
            if (timeout == null) {
                inhibitorTimeout.stop();
                return ;
            }
            timeout -= 1;
            if (timeout <= 0) {
                removeManualInhibitor();
                return ;
            }
        }
    }

}
