// Saturation, as a nudge rather than a stored number.
//
// There is no saturation preference: `setSaturation` re-saturates the palette
// that is in effect right now, which makes it compounding -- committing 1.5
// twice really is 2.25. So the row keeps the reading it has shown you and
// commits the RATIO between the old reading and the new one, which makes the
// number on screen an honest total rather than a lever that lies the second
// time it is pulled. Selecting a different theme resets the reading to neutral,
// because the new palette is a new ground.
//
// The commit happens on release only. A drag through 0.6 → 0.9 → 1.4 would
// otherwise rewrite all nineteen tokens at every pixel, and each rewrite is
// lossy: HSV saturation cannot be recovered once it has been rounded to a hex.

import QtQuick
import qs.config
import qs.services

SettingRow {
    id: root

    label: "Saturation"
    detail: "Shifts every derived surface and text tone together"
    controlWidth: 280

    // 1.0 is the palette as it stands. Range 0 – 2, shown as 0 – 200%.
    property real shown: 1
    property real committed: 1

    readonly property real maximum: 2

    // A theme change replaces the ground this row was measuring against.
    readonly property string activeId: ThemeProfiles.activeId
    onActiveIdChanged: {
        root.shown = 1;
        root.committed = 1;
    }

    function apply(): void {
        if (Math.abs(root.shown - root.committed) < 0.005)
            return;
        // Dividing by the last reading turns an absolute slider into the
        // relative factor the service actually takes.
        const factor = root.committed > 0.02 ? root.shown / root.committed : root.maximum;
        if (ThemeProfiles.setSaturation(Math.max(0, Math.min(root.maximum, factor))))
            root.committed = root.shown;
        else
            root.shown = root.committed;
    }

    function moveTo(ratio: real): void {
        root.shown = Math.round(Math.max(0, Math.min(1, ratio)) * root.maximum * 100) / 100;
    }

    function step(direction: int): void {
        root.moveTo((root.shown + direction * 0.05) / root.maximum);
        root.apply();
    }

    Item {
        id: control

        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.shown * 100) + " percent, range 0 to 200"
        Accessible.focusable: true
        Accessible.focused: control.activeFocus
        Accessible.onIncreaseAction: root.step(1)
        Accessible.onDecreaseAction: root.step(-1)

        Keys.onPressed: event => {
            if (event.key === Qt.Key_Left || event.key === Qt.Key_Down) {
                root.step(-1);
                event.accepted = true;
            } else if (event.key === Qt.Key_Right || event.key === Qt.Key_Up) {
                root.step(1);
                event.accepted = true;
            } else if (event.key === Qt.Key_Home) {
                root.moveTo(0);
                root.apply();
                event.accepted = true;
            } else if (event.key === Qt.Key_End) {
                root.moveTo(1);
                root.apply();
                event.accepted = true;
            }
        }

        Rectangle {
            id: frame

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

            // Written out rather than reusing ValueSlider: this row needs the
            // release, and ValueSlider reports only movement.
            Rectangle {
                id: track

                anchors.left: parent.left
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                anchors.margins: 4
                height: 10
                radius: 5
                color: Theme.alpha(Theme.fg, 0.12)
                border.width: 0

                Rectangle {
                    id: fill

                    anchors.left: parent.left
                    anchors.top: parent.top
                    anchors.bottom: parent.bottom
                    width: parent.width * Math.max(0, Math.min(1, root.shown / root.maximum))
                    radius: parent.radius
                    border.width: 0
                    gradient: Gradient {
                        orientation: Gradient.Horizontal
                        GradientStop { position: 0.0; color: Theme.accent }
                        GradientStop { position: 1.0; color: Theme.accentSecondary }
                    }
                }

                Rectangle {
                    width: 16
                    height: 16
                    radius: 8
                    border.width: 0
                    color: Theme.fg
                    anchors.verticalCenter: parent.verticalCenter
                    x: Math.max(0, Math.min(parent.width - width, fill.width - width / 2))
                    visible: drag.containsMouse || drag.pressed
                }

                MouseArea {
                    id: drag

                    anchors.fill: parent
                    anchors.margins: -8
                    hoverEnabled: true
                    cursorShape: Qt.PointingHandCursor

                    function ratioAt(mouseX: real): real {
                        return (mouseX - 8) / track.width;
                    }

                    onPressed: event => root.moveTo(drag.ratioAt(event.x))
                    onPositionChanged: event => {
                        if (drag.pressed)
                            root.moveTo(drag.ratioAt(event.x));
                    }
                    onReleased: root.apply()
                    onWheel: event => {
                        root.moveTo((root.shown + (event.angleDelta.y > 0 ? 0.05 : -0.05))
                            / root.maximum);
                        root.apply();
                    }
                }
            }
        }

        Text {
            id: readout

            anchors.right: parent.right
            anchors.verticalCenter: parent.verticalCenter
            width: 56
            horizontalAlignment: Text.AlignRight
            text: Math.round(root.shown * 100) + "%"
            color: Theme.fgDim
            font.family: Theme.fontFamily
            font.features: Theme.tabularFigures
            font.pixelSize: Theme.fontSizeSmall
        }
    }
}
