import Quickshell
import Quickshell.Io
import QtQuick

import qs.config
import qs.services

ShellRoot {
    IpcHandler {
        target: "displays-test"

        function status(): string {
            const monitor = Displays.monitors.length > 0 ? Displays.monitors[0] : null;
            return JSON.stringify({
                count: Displays.monitors.length,
                name: monitor ? monitor.name : "",
                width: monitor ? monitor.width : 0,
                height: monitor ? monitor.height : 0,
                refresh: monitor ? monitor.refreshRate : 0,
                mode: monitor ? monitor.mode : "",
                scale: monitor ? monitor.scale : 0,
                transform: monitor ? monitor.transform : -1,
                x: monitor ? monitor.x : 0,
                y: monitor ? monitor.y : 0,
                primary: monitor ? monitor.primary : false,
                modes: monitor ? monitor.modes.length : 0,
                awaiting: Displays.awaitingConfirmation,
                canConfirm: Displays.canConfirm,
                secondsLeft: Displays.secondsLeft,
                lastError: Displays.lastError,
                overridden: monitor ? Displays.isOverridden(monitor.name) : false
            });
        }

        function applyScale(scale: real): bool {
            const monitor = Displays.monitors[0];
            if (!monitor) return false;
            const mode = monitor.mode;
            return Displays.apply(monitor.name, mode, scale, monitor.transform);
        }

        function transactionStatus(): string {
            return JSON.stringify({
                layout: Displays.currentLayout(),
                pending: Displays.pendingRequestedLayout,
                previous: Displays.pendingPreviousLayout,
                reverting: Displays.revertExpectedLayout,
                awaiting: Displays.awaitingConfirmation,
                canConfirm: Displays.canConfirm,
                busy: Displays.busy,
                generation: Displays.operationGeneration,
                revertGeneration: Displays.revertGeneration,
                lastError: Displays.lastError
            });
        }

        function applyLayoutFixture(secondX: int, secondY: int): bool {
            const layout = Displays.currentLayout();
            if (layout.length !== 2) return false;
            layout[0].x = 0;
            layout[0].y = 0;
            layout[0].primary = true;
            layout[1].x = secondX;
            layout[1].y = secondY;
            layout[1].primary = false;
            return Displays.applyLayout(layout);
        }

        function makePrimaryFixture(output: string): bool {
            return Displays.makePrimary(output);
        }

        function injectReadback(text: string, generation: int): void {
            Displays.parse(text, generation);
        }

        function expireApplyVerification(): void {
            Displays.verificationTimedOut();
        }

        function expireRevertVerification(): void {
            Displays.revertVerificationTimedOut();
        }

        function refreshIdentityFixture(): string {
            const modes = Displays.normaliseModes([
                "1920x1080@59.94Hz",
                "1920x1080@60.00Hz"
            ]);
            const monitor = { width: 1920, height: 1080, refreshRate: 59.94 };
            return JSON.stringify({
                count: modes.length,
                modes: modes.map(mode => mode.mode),
                selected: modes.filter(mode => Displays.modeIsCurrent(monitor, mode)).map(mode => mode.mode)
            });
        }

        function positionFixture(): string {
            const previous = Displays.monitors;
            Displays.parse(JSON.stringify([
                {
                    name: "DP-2", description: "Primary", width: 4500, height: 3000,
                    refreshRate: 60, scale: 1.5, transform: 0, x: 140, y: 80,
                    availableModes: ["4500x3000@60.00Hz"]
                },
                {
                    name: "HDMI-A-1", description: "Second", width: 2560, height: 1440,
                    refreshRate: 60, scale: 1, transform: 0, x: 3140, y: 80,
                    availableModes: ["2560x1440@60.00Hz"]
                }
            ]), Displays.operationGeneration);
            const result = JSON.stringify(Displays.monitors.map(monitor => ({
                name: monitor.name,
                x: monitor.x,
                y: monitor.y,
                primary: monitor.primary
            })));
            Displays.monitors = previous;
            return result;
        }

        function applyBad(kind: string): bool {
            const monitor = Displays.monitors[0];
            if (!monitor) return false;
            const mode = monitor.mode;
            if (kind === "mode") return Displays.apply(monitor.name, "9999x9999@240", monitor.scale, monitor.transform);
            if (kind === "scale") return Displays.apply(monitor.name, mode, 1.37, monitor.transform);
            if (kind === "dirtyScale") {
                const dirty = Displays.scales.find(scale => !Displays.isScaleClean(mode, scale));
                return dirty === undefined ? false : Displays.apply(monitor.name, mode, dirty, monitor.transform);
            }
            if (kind === "transform") return Displays.apply(monitor.name, mode, monitor.scale, 9);
            if (kind === "output") return Displays.apply("NOPE-1", mode, monitor.scale, monitor.transform);
            return false;
        }

        function confirmChange(): bool { return Displays.confirm(); }
        function revertChange(): void { Displays.revert(); }
        function forget(): void {
            const monitor = Displays.monitors[0];
            if (monitor) Displays.forget(monitor.name);
        }
        function refresh(): void { Displays.refresh(); }
    }
}
