// Appearance — the page the rest of the settings vocabulary was built for.
//
// Before Stage 3 this page adjusted a clock format and three vitals toggles,
// and its "Theme" card was two rows of text pretending to be controls. It now
// drives the compositor directly: every row here is applied through
// `hyprctl eval` and confirmed by reading the value back before it is stored.
//
// The preview is pinned above the controls rather than sitting inline, because
// the numbers are meaningless on their own -- "outer gaps 24" only means
// something once you have watched the windows move apart by that much, at the
// scale of the display you actually use.

import QtQuick
import qs.config
import qs.services

SettingsPage {
    id: root

    property string expandedPicker: ""

    // Whether the accent's HSV fine-tune is open. Collapsed by default: it is
    // six sliders that answer a question the four colour wells above have
    // usually already answered.
    property bool fineTuneOpen: false

    // Which group of cards is on screen. Themes leads deliberately: light and
    // dark is the control reached most often, and it used to be the third
    // section down, below a wallpaper grid and the whole lock screen.
    property string tab: "themes"

    // Arriving from another page that named a section opens on it. Taken once
    // rather than bound, so the tabs still work normally afterwards. The old
    // `theme` id still resolves: deep links, IPC calls and muscle memory all
    // hold it, and it means the same thing this tab does.
    Component.onCompleted: {
        const section = ShellState.takeSettingsSection();
        if (section === "theme")
            root.tab = "themes";
        else if (section !== "")
            root.tab = section;
    }

    title: "Appearance"
    lede: "Tune the Prism shell and the applications that live inside it. The preview above is your real geometry, to scale."

    header: Component {
        Column {
            spacing: 9

            DesktopPreview {
                width: parent.width
            }

            Text {
                width: parent.width
                horizontalAlignment: Text.AlignHCenter
                text: SystemSettings.lastError !== ""
                    ? SystemSettings.lastError
                    : "Live preview — the focused window wears the prism border"
                color: SystemSettings.lastError !== "" ? Theme.warn : Theme.fgMuted
                font.family: Theme.fontFamily
                font.pixelSize: Theme.fontSizeSmall
                elide: Text.ElideRight
            }
        }
    }

    SettingsTabs {
        tabs: [
            { value: "themes", label: "Themes" },
            { value: "editor", label: "Theme editor" },
            { value: "background", label: "Background" },
            { value: "type", label: "Typography" },
            { value: "windows", label: "Windows" },
        ]
        current: root.tab
        onSelected: value => root.tab = value
    }

    SettingsCard {
        visible: root.tab === "background"
        title: "Background"
        subtitle: Wallpaper.lastError !== ""
            ? Wallpaper.lastError
            : "Applied to every display, from the folder below."

        TextEntryRow { setting: "wallpaperDir"; placeholder: "Pictures/Wallpapers" }

        WallpaperControls {
            id: wallpaperControls
            width: parent.width
        }

        WallpaperPicker {
            id: wallpapers
            width: parent.width
            mode: wallpaperControls.mode
            selectedOutput: wallpaperControls.selectedOutput
        }

        ActionRow {
            visible: wallpapers.hidden > 0 || wallpapers.expanded
            label: wallpapers.expanded ? "Showing every image" : wallpapers.hidden + " more available"
            detail: "The grid is kept short so the rest of this page stays reachable"
            action: wallpapers.expanded ? "Show fewer" : "Show all"
            onTriggered: wallpapers.expanded = !wallpapers.expanded
        }

        ActionRow {
            label: "Look for new images"
            detail: Wallpaper.scanning
                ? "Scanning…"
                : Wallpaper.available.length + " image" + (Wallpaper.available.length === 1 ? "" : "s") + " found"
            action: "Rescan"
            divider: false
            enabled: !Wallpaper.scanning
            onTriggered: Wallpaper.rescan()
        }
    }

    SettingsCard {
        visible: root.tab === "background"
        title: "Video playback"
        subtitle: VideoWallpaper.lastError !== ""
            ? VideoWallpaper.lastError
            : "Videos loop muted and decode on the GPU. Considerate by default — a video wallpaper should never cost you a frame you care about."

        TextEntryRow { setting: "videoWallpaperDir"; placeholder: "Videos/Wallpapers" }

        ToggleRow { setting: "videoWallpaperPauseOnBattery" }

        TextRow {
            label: "During games and fullscreen"
            detail: "Pauses automatically — not optional, and free"
            value: "Automatic"
        }

        TextRow {
            label: "Pause from the bar"
            detail: "While a video plays, a pill sits in the bar — one click pauses it, for remote desktop or just quiet"
            value: ""
        }

        TextRow {
            label: "Lock screen"
            detail: "Uses a still frame of the video — hyprlock cannot play motion"
            value: "Still frame"
        }

        ActionRow {
            label: "Look for new videos"
            detail: VideoWallpaper.available
                ? VideoWallpaper.candidates.length + " video" + (VideoWallpaper.candidates.length === 1 ? "" : "s") + " found"
                : "mpvpaper is not installed — run panama update to pick it up"
            action: "Rescan"
            divider: false
            enabled: VideoWallpaper.available
            onTriggered: VideoWallpaper.rescan()
        }
    }

    SettingsCard {
        visible: root.tab === "background"
        title: "Lock screen"
        subtitle: LockScreen.lastError !== ""
            ? LockScreen.lastError
            : "A representative preview of the screen shown before authentication."

        LockScreenPreview {
            width: parent.width
        }

        ChoiceRow { setting: "lockBackgroundMode" }
        SliderRow { setting: "lockBlurLevel"; zeroLabel: "Off" }
        ToggleRow { setting: "lockShowClock" }
        ToggleRow { setting: "lockShowDate" }
        ToggleRow { setting: "lockShowUser" }
        ToggleRow { setting: "lockFadeOnEmpty"; divider: false }
    }

    // ── Themes ──────────────────────────────────────────────────────────────
    //
    // The gallery is the page, not a card on it. Cards would put a heading and
    // a border around each of two lists that are already visually separate, and
    // the theme cards themselves are the only surfaces here that need edges.

    ThemeModeHero {
        visible: root.tab === "themes"
        width: parent.width
    }

    Text {
        visible: root.tab === "themes" && ThemeCatalog.lastError !== ""
        width: parent.width
        text: ThemeCatalog.lastError
        color: Theme.warn
        font.family: Theme.fontFamily
        font.pixelSize: Theme.fontSizeSmall
        wrapMode: Text.WordWrap
    }

    ThemeGallery {
        visible: root.tab === "themes"
        width: parent.width
        scheme: "dark"
        heading: "Dark themes"
    }

    ThemeGallery {
        visible: root.tab === "themes"
        width: parent.width
        scheme: "light"
        heading: "Light themes"
    }

    // Dashed rather than solid, and the width of the page: this is a door out
    // of the gallery, not an eleventh theme in it.
    Rectangle {
        id: buildLink

        visible: root.tab === "themes"
        width: parent.width
        implicitHeight: buildCopy.implicitHeight + 30
        radius: Theme.cardRadius + 2
        color: Theme.alpha(Theme.accent, buildHover.hovered ? 0.12 : 0.07)
        border.width: buildLink.activeFocus ? 2 : 1
        border.color: buildLink.activeFocus
            ? Theme.accentSecondary : Theme.alpha(Theme.accent, 0.35)
        activeFocusOnTab: true

        Accessible.role: Accessible.Button
        Accessible.name: "Build your own theme"
        Accessible.description: "Opens the theme editor"
        Accessible.focusable: true
        Accessible.focused: buildLink.activeFocus

        Keys.onReturnPressed: root.tab = "editor"
        Keys.onSpacePressed: root.tab = "editor"

        Text {
            id: buildGlyph
            anchors.left: parent.left
            anchors.leftMargin: 17
            anchors.verticalCenter: parent.verticalCenter
            text: "◐"
            color: Theme.accent
            font.family: Theme.fontFamily
            font.pixelSize: 20
        }

        Column {
            id: buildCopy

            anchors.left: buildGlyph.right
            anchors.leftMargin: 13
            anchors.right: buildArrow.left
            anchors.rightMargin: 13
            anchors.verticalCenter: parent.verticalCenter
            spacing: 3

            Text {
                width: parent.width
                text: "Build your own theme"
                color: Theme.fg
                font.family: Theme.fontFamily
                font.pixelSize: Theme.fontSize
                font.weight: Font.DemiBold
            }

            Text {
                width: parent.width
                text: "Primary, secondary, background, foreground, effects — every colour yours, saved as a theme that lives in the galleries above"
                color: Theme.fgDim
                font.family: Theme.fontFamily
                font.pixelSize: Theme.fontSizeSmall
                wrapMode: Text.WordWrap
            }
        }

        Text {
            id: buildArrow
            anchors.right: parent.right
            anchors.rightMargin: 17
            anchors.verticalCenter: parent.verticalCenter
            text: "→"
            color: Theme.accent
            font.family: Theme.fontFamily
            font.pixelSize: 17
        }

        HoverHandler {
            id: buildHover
            cursorShape: Qt.PointingHandCursor
        }

        TapHandler {
            onTapped: root.tab = "editor"
        }
    }

    // ── Theme editor ────────────────────────────────────────────────────────

    SettingsCard {
        id: editorCard

        visible: root.tab === "editor"
        title: "Your theme"
        // The identity of what is being edited, always. Failures get their own
        // line below rather than displacing it -- a subtitle that sometimes
        // says which theme you are editing and sometimes says something went
        // wrong answers neither question reliably.
        subtitle: ThemeProfiles.activeProfile.shipped === true
            ? ThemeProfiles.activeProfile.name
                + " — editing it forks a copy you can name below"
            : "Based on " + ThemeProfiles.activeProfile.name
                + " · every change previews live on the real desktop"

        Text {
            width: parent.width
            visible: wells.lastError !== "" || ColorScheme.lastError !== ""
            text: wells.lastError !== "" ? wells.lastError : ColorScheme.lastError
            color: Theme.warn
            font.family: Theme.fontFamily
            font.pixelSize: Theme.fontSizeSmall
            wrapMode: Text.WordWrap
            bottomPadding: 10
        }

        ThemeStartChips {
            width: parent.width
            bottomPadding: 13
        }

        SegmentRow {
            label: "Scheme"
            detail: "Flipping sides returns to the theme you last chose there"
            options: [{ value: "dark", label: "Dark" }, { value: "light", label: "Light" }]
            value: ThemeProfiles.scheme
            onSelected: value => ThemeProfiles.setScheme(value)
        }

        Item { width: 1; height: 13 }

        ThemeEditorWells {
            id: wells
            width: parent.width
        }

        Item { width: 1; height: 13 }

        ThemeSaturationRow {
            width: parent.width
        }

        ActionRow {
            label: "Fine-tune"
            detail: "Hue, saturation and value for each end of the accent"
            action: root.fineTuneOpen ? "Close" : "Open"
            onTriggered: root.fineTuneOpen = !root.fineTuneOpen
        }

        AccentEditor {
            visible: root.fineTuneOpen
            width: parent.width
        }

        ThemeSaveRow {
            width: parent.width
        }
    }

    // One selector for every font. The two always-open lists and the
    // open-one-at-a-time disclosure both retire: a closed dropdown per row
    // reads as five choices instead of a wall of samples, and each row names
    // what it actually controls — the old tab never said which font was the
    // shell's and which was the applications'.
    SettingsCard {
        visible: root.tab === "type"
        title: "Fonts"
        subtitle: {
            if (Fonts.lastError !== "")
                return Fonts.lastError;
            if (DesktopStyle.lastError !== "")
                return DesktopStyle.lastError;
            return "Each row names what it controls. The menu shows every family in its own face — type to filter.";
        }

        SettingRow {
            label: "Interface"
            detail: Fonts.interfaceMissing
                ? "Not installed — fontconfig is substituting something else"
                : "The shell — bar, dock, notifications, this window"
            divider: false
            controlWidth: 8
        }

        FontPicker {
            width: parent.width
            families: Fonts.interfaceFonts
            current: Fonts.interfaceFont
            emptyText: Fonts.scanning ? "Reading installed fonts…" : "No interface fonts found"
            onPicked: family => Fonts.setInterface(family)
        }

        SettingRow {
            label: "Icons"
            detail: Fonts.iconMissing
                ? "Not installed — the shell's glyphs will not draw correctly"
                : "Glyphs only, never text — needs a Nerd Font"
            divider: false
            controlWidth: 8
        }

        FontPicker {
            width: parent.width
            families: Fonts.iconFonts
            current: Fonts.iconFont
            emptyText: "No Nerd Fonts installed"
            onPicked: family => Fonts.setIcon(family)
        }

        SettingRow {
            label: "Application"
            detail: "GTK and libadwaita apps that follow the desktop default"
            divider: false
            controlWidth: 8
        }

        FontPicker {
            width: parent.width
            families: Fonts.interfaceFonts
            current: DesktopStyle.applicationFont
            emptyText: Fonts.scanning ? "Reading installed fonts…" : "No application fonts found"
            onPicked: family => DesktopStyle.setApplicationFont(family)
        }

        SettingRow {
            label: "Document"
            detail: "Long-form reading, where applications ask for it"
            divider: false
            controlWidth: 8
        }

        FontPicker {
            width: parent.width
            families: Fonts.interfaceFonts
            current: DesktopStyle.documentFont
            emptyText: Fonts.scanning ? "Reading installed fonts…" : "No document fonts found"
            onPicked: family => DesktopStyle.setDocumentFont(family)
        }

        SettingRow {
            label: "Monospace"
            detail: "Terminals and code, wherever fixed width is asked for"
            divider: false
            controlWidth: 8
        }

        FontPicker {
            width: parent.width
            families: Fonts.monospaceFonts
            current: DesktopStyle.monospaceFont
            emptyText: Fonts.scanning ? "Reading installed fonts…" : "No monospace fonts found"
            onPicked: family => DesktopStyle.setMonospaceFont(family)
        }
    }

    SettingsCard {
        visible: root.tab === "type"
        title: "Sizes"
        subtitle: "The interface size moves the shell's whole scale; the rest are per role."

        SliderRow { setting: "interfaceFontSize" }
        SliderRow { setting: "applicationFontSize" }
        SliderRow { setting: "documentFontSize" }
        SliderRow { setting: "monospaceFontSize"; divider: false }
    }

    SettingsCard {
        visible: root.tab === "type"
        title: "Rendering"

        ChoiceRow { setting: "fontHinting" }
        ChoiceRow { setting: "fontAntialiasing"; divider: false }
    }

    SettingsCard {
        visible: root.tab === "type"
        title: "Icons & pointer"
        subtitle: DesktopStyle.lastError !== ""
            ? DesktopStyle.lastError
            : "Installed themes only. The pointer updates in applications and Hyprland together."

        ActionRow {
            label: "Application icons"
            detail: DesktopStyle.iconTheme
            action: root.expandedPicker === "icon-theme" ? "Close" : "Choose"
            enabled: DesktopStyle.catalogLoaded
            onTriggered: root.expandedPicker = root.expandedPicker === "icon-theme" ? "" : "icon-theme"
        }

        SearchPicker {
            visible: root.expandedPicker === "icon-theme"
            width: parent.width
            items: DesktopStyle.iconThemes
            current: DesktopStyle.iconTheme
            placeholder: "Search icon themes"
            emptyText: DesktopStyle.scanning ? "Reading installed icon themes…" : "No icon themes found"
            onPicked: value => {
                if (DesktopStyle.setIconTheme(value))
                    root.expandedPicker = "";
            }
        }

        ActionRow {
            label: "Pointer theme"
            detail: DesktopStyle.cursorTheme
            action: root.expandedPicker === "cursor-theme" ? "Close" : "Choose"
            enabled: DesktopStyle.catalogLoaded
            divider: false
            onTriggered: root.expandedPicker = root.expandedPicker === "cursor-theme" ? "" : "cursor-theme"
        }

        SearchPicker {
            visible: root.expandedPicker === "cursor-theme"
            width: parent.width
            items: DesktopStyle.cursorThemes
            current: DesktopStyle.cursorTheme
            placeholder: "Search pointer themes"
            emptyText: DesktopStyle.scanning ? "Reading installed pointer themes…" : "No pointer themes found"
            onPicked: value => {
                if (DesktopStyle.setCursorTheme(value))
                    root.expandedPicker = "";
            }
        }
    }

    SettingsCard {
        visible: root.tab === "windows"
        title: "Titlebars"
        subtitle: "One rule for GNOME applications and Panama's own windows. There is no minimize or maximize toggle: Hyprland has no minimize, so the buttons would be lies."

        ToggleRow { setting: "panamaTitlebar" }
        ChoiceRow { setting: "titlebarButtonSide"; divider: false }
    }

    SettingsCard {
        visible: root.tab === "windows"
        title: "Windows"
        subtitle: "Spacing and shape of tiled windows. Each change is applied to the compositor and confirmed before it is saved."

        SliderRow { setting: "windowRounding" }
        SliderRow { setting: "gapsIn" }
        SliderRow { setting: "gapsOut" }
        SliderRow { setting: "borderSize"; zeroLabel: "None" }
        SliderRow { setting: "roundingPower" }
        SliderRow { setting: "inactiveOpacity" }
        SliderRow { setting: "activeOpacity" }
        SliderRow { setting: "fullscreenOpacity"; divider: false }
    }

    // Effects belong to the theme now: saving snapshots all ten values into the
    // record, and applying a theme that carries them puts them back. They sit
    // in the editor rather than beside the galleries for exactly that reason.
    SettingsCard {
        visible: root.tab === "editor"
        title: "Effects"
        subtitle: "Part of your theme — corners, blur, shadows, glow and motion save with it. Each costs frame time; turning one off is a legitimate way to buy it back while gaming."

        ToggleRow { setting: "blurEnabled" }
        SliderRow { setting: "blurSize" }
        SliderRow { setting: "blurPasses" }
        ToggleRow { setting: "shadowEnabled" }
        SliderRow { setting: "shadowRange"; zeroLabel: "None" }
        SliderRow { setting: "shadowRenderPower" }
        ToggleRow { setting: "shadowSharp" }
        ToggleRow { setting: "glowEnabled" }
        SliderRow { setting: "glowRange"; zeroLabel: "None" }
        ToggleRow { setting: "animationsEnabled"; divider: false }
    }

}
