// Advanced accent editing remains a labelled, keyboard-operable extension of
// the named fast path. Hue is always accompanied by saturation, value, a
// numeric readout, and the two-colour preview supplied by Appearance.

import QtQuick
import Quickshell
import Quickshell.Io
import qs.config
import qs.services
import qs.widgets
import "../../services/ThemeProfileModel.js" as ThemeProfileModel

Column {
    id: editor

    width: parent ? parent.width : 620
    spacing: 0

    property string pickerTarget: "primary"
    property string lastError: ""

    readonly property var primaryHsv: ThemeProfileModel.hexToHsv(
        ThemeProfiles.activeProfile.accent) || ({ h: 0, s: 0, v: 0 })
    readonly property var secondaryHsv: ThemeProfileModel.hexToHsv(
        ThemeProfiles.activeProfile.secondary) || ({ h: 0, s: 0, v: 0 })

    function changeChannel(target: string, channel: string, ratio: real): void {
        const source = target === "primary" ? editor.primaryHsv : editor.secondaryHsv;
        const next = { h: source.h, s: source.s, v: source.v };
        next[channel] = Math.round(Math.max(0, Math.min(1, ratio))
            * (channel === "h" ? 360 : 100));
        const changed = ThemeProfileModel.hsvToHex(next.h, next.s, next.v);
        const primary = target === "primary" ? changed : ThemeProfiles.activeProfile.accent;
        const secondary = target === "secondary" ? changed : ThemeProfiles.activeProfile.secondary;
        ThemeProfiles.setAccentPair(primary, secondary);
    }

    function pick(target: string): void {
        if (screenPicker.running)
            return;
        editor.pickerTarget = target;
        editor.lastError = "";
        screenPicker.exec(["hyprpicker", "--format=hex", "--lowercase-hex", "--quiet", "--no-fancy"]);
    }

    function acceptPicked(value: string): void {
        const picked = String(value).trim().toLowerCase();
        if (ThemeProfileModel.hexToHsv(picked) === null) {
            editor.lastError = "The sampled colour was not valid.";
            return;
        }
        const primary = editor.pickerTarget === "primary"
            ? picked : ThemeProfiles.activeProfile.accent;
        const secondary = editor.pickerTarget === "secondary"
            ? picked : ThemeProfiles.activeProfile.secondary;
        ThemeProfiles.setAccentPair(primary, secondary);
    }

    component HsvRow: SettingRow {
        id: root

        required property string target
        required property string channel
        required property real channelValue
        required property real channelMaximum
        property string suffix: "%"

        controlWidth: 280

        Item {
            id: keyboardSlider

            anchors.right: parent.right
            anchors.verticalCenter: parent.verticalCenter
            width: 270
            height: 32
            activeFocusOnTab: true

            Accessible.role: Accessible.Slider
            Accessible.name: root.label
            Accessible.description: Math.round(root.channelValue) + root.suffix
                + ", range 0 to " + root.channelMaximum
            Accessible.focusable: true
            Accessible.focused: activeFocus
            Accessible.onIncreaseAction: keyboardSlider.step(1)
            Accessible.onDecreaseAction: keyboardSlider.step(-1)

            function step(direction: int): void {
                const increment = root.channel === "h" ? 1 : 1;
                const value = Math.max(0, Math.min(root.channelMaximum,
                    root.channelValue + direction * increment));
                editor.changeChannel(root.target, root.channel, value / root.channelMaximum);
            }

            Keys.onPressed: event => {
                if (event.key === Qt.Key_Left || event.key === Qt.Key_Down) {
                    keyboardSlider.step(-1);
                    event.accepted = true;
                } else if (event.key === Qt.Key_Right || event.key === Qt.Key_Up) {
                    keyboardSlider.step(1);
                    event.accepted = true;
                } else if (event.key === Qt.Key_Home) {
                    editor.changeChannel(root.target, root.channel, 0);
                    event.accepted = true;
                } else if (event.key === Qt.Key_End) {
                    editor.changeChannel(root.target, root.channel, 1);
                    event.accepted = true;
                }
            }

            Rectangle {
                anchors.left: parent.left
                anchors.right: readout.left
                anchors.rightMargin: 10
                anchors.verticalCenter: parent.verticalCenter
                height: 24
                radius: 9
                color: "transparent"
                border.width: keyboardSlider.activeFocus ? 2 : 1
                border.color: keyboardSlider.activeFocus ? Theme.accentSecondary : Theme.alpha(Theme.fg, 0.08)

                ValueSlider {
                    anchors.fill: parent
                    anchors.margins: 4
                    value: root.channelMaximum > 0 ? root.channelValue / root.channelMaximum : 0
                    onMoved: ratio => editor.changeChannel(root.target, root.channel, ratio)
                }
            }

            Text {
                id: readout
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                width: 56
                horizontalAlignment: Text.AlignRight
                text: Math.round(root.channelValue) + root.suffix
                color: Theme.fgDim
                font.family: Theme.fontFamily
                font.features: Theme.tabularFigures
                font.pixelSize: Theme.fontSizeSmall
            }
        }
    }

    HsvRow {
        target: "primary"; channel: "h"; channelValue: editor.primaryHsv.h; channelMaximum: 360
        suffix: "°"; label: "Primary hue"; detail: "Colour family, measured from 0 to 360 degrees"
    }
    HsvRow {
        target: "primary"; channel: "s"; channelValue: editor.primaryHsv.s; channelMaximum: 100
        label: "Primary saturation"; detail: "Colour intensity from grey to vivid"
    }
    HsvRow {
        target: "primary"; channel: "v"; channelValue: editor.primaryHsv.v; channelMaximum: 100
        label: "Primary value"; detail: "Brightness from black to full colour"
    }
    HsvRow {
        target: "secondary"; channel: "h"; channelValue: editor.secondaryHsv.h; channelMaximum: 360
        suffix: "°"; label: "Secondary hue"; detail: "Colour family at the far end of the Prism gradient"
    }
    HsvRow {
        target: "secondary"; channel: "s"; channelValue: editor.secondaryHsv.s; channelMaximum: 100
        label: "Secondary saturation"; detail: "Colour intensity from grey to vivid"
    }
    HsvRow {
        target: "secondary"; channel: "v"; channelValue: editor.secondaryHsv.v; channelMaximum: 100
        label: "Secondary value"; detail: "Brightness from black to full colour"
    }

    SettingRow {
        label: "Pick colour from screen"
        detail: editor.lastError !== ""
            ? editor.lastError
            : "Sample either end of the accent gradient with hyprpicker"
        divider: false
        controlWidth: 330

        Row {
            anchors.right: parent.right
            anchors.verticalCenter: parent.verticalCenter
            spacing: 7

            SettingsButton {
                text: "Pick primary from screen"
                enabled: !screenPicker.running
                activeFocusOnTab: enabled
                border.width: activeFocus ? 2 : 1
                border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08)
                onClicked: editor.pick("primary")
                Keys.onReturnPressed: if (enabled) editor.pick("primary")
                Keys.onSpacePressed: if (enabled) editor.pick("primary")
            }

            SettingsButton {
                text: "Pick secondary from screen"
                enabled: !screenPicker.running
                activeFocusOnTab: enabled
                border.width: activeFocus ? 2 : 1
                border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08)
                onClicked: editor.pick("secondary")
                Keys.onReturnPressed: if (enabled) editor.pick("secondary")
                Keys.onSpacePressed: if (enabled) editor.pick("secondary")
            }
        }
    }

    Process {
        id: screenPicker

        stdout: StdioCollector {
            onStreamFinished: editor.acceptPicked(this.text)
        }
        onExited: (exitCode, exitStatus) => {
            if (exitCode !== 0)
                editor.lastError = "Screen colour picking was cancelled or unavailable.";
        }
    }
}
