pragma ComponentBehavior: Bound

import Quickshell
import Quickshell.Io
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Paths
import qs.Services
import qs.Modules.Settings.Common

PageBase {
	id: root

	readonly property list<string> fonts: Qt.fontFamilies()
	readonly property var schemes: [
		{
			id: "onedark",
			label: qsTr("One Dark")
		},
		{
			id: "nord",
			label: qsTr("Nord")
		},
		{
			id: "dracula",
			label: qsTr("Dracula")
		},
		{
			id: "darkgreen",
			label: qsTr("Darkgreen")
		},
		{
			id: "solarized",
			label: qsTr("Solarized")
		},
		{
			id: "rosepine",
			label: qsTr("Rosepine")
		},
		{
			id: "gruvbox",
			label: qsTr("Gruvbox")
		},
		{
			id: "catppuccin",
			label: qsTr("Catppuccin")
		},
		{
			id: "tokyonight",
			label: qsTr("Tokyo Night")
		},
		{
			id: "shadotheme",
			label: qsTr("Shadotheme")
		}
	]

	isSubPage: true
	title: qsTr("Colors & font")

	ColumnLayout {
		anchors.horizontalCenter: parent.horizontalCenter
		anchors.top: parent.top
		spacing: Tokens.spacing.extraSmall / 2
		width: root.cappedWidth

		SectionHeader {
			first: true
			text: qsTr("Colors")
		}

		ToggleRow {
			text: qsTr("Dynamic colors")
			first: true
			subtext: qsTr("Automatic color scheme based on wallpaper is %1").arg(Config.colors.schemeGen ? "enabled" : "disabled")
			checked: Config.colors.schemeGen
			settingAnchor: "colors-fonts-dynamic-colors"

			onToggled: {
				Config.colors.schemeGen = checked;

				if (checked)
					Colors.setMode(Config.colors.mode);
			}
		}

		DialogSelectButton {
			settingAnchor: "colors-fonts-preset-scheme"
			model: root.schemes
			acceptLabel: qsTr("Confirm")
			enabled: !Config.colors.schemeGen
			header: qsTr("Select scheme")
			rowButton.activeItem: root.schemes.find(s => {
				var regex = new RegExp(Config.colors.presets.name, "i");
				return regex.test(s.id);
			}).label ?? ""
			label: qsTr("Preset scheme")
			subtext: qsTr("Select preset color scheme")
			rootParent: root.flickable

			FileView {
				id: view
				path: `${Paths.state}/presets.json`

				watchChanges: true
				onFileChanged: reload()

				JsonAdapter {
					id: adapter

					property var presets
				}
			}

			initialSelect: Config.colors.presets.name.toLowerCase()

			onAccepted: {
				if (!selectedItem)
					return;

				const s = selectedItem.toLowerCase();
				let v = "";
				let a = "";
				const existingVariant = Config.colors.presets.variant;
				const existingAccent = Config.colors.presets.accent;
				const variantKeys = Object.keys(adapter.presets[s].variants);

				if (existingVariant !== "" && variantKeys.some(v => v === existingVariant))
					v = existingVariant;

				if (v !== "" && existingAccent !== "" && adapter.presets[s].variants[v]?.accents.some(a => a === existingAccent))
					a = existingAccent;

				if (a !== "")
					Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`, "-a", `${a}`]);
				else if (v !== "")
					Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`]);
				else
					Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${variantKeys[0]}`]);
			}
		}

		DialogSelectButton {
			settingAnchor: "colors-fonts-preset-variant"
			// qmlformat off
			model: {
				const v = adapter.presets[Config.colors.presets.name].variants;
				const map = Object.keys(v).map(v => ({
					id: v,
					label: qsTr("%1%2")
						.arg(v.charAt(0).toUpperCase())
						.arg(v.slice(1).toLowerCase())
				}));

				return map;
			}
			// qmlformat on
			acceptLabel: qsTr("Confirm")
			enabled: !Config.colors.schemeGen && model.length > 1
			header: qsTr("Select variant")
			rowButton.activeItem: {
				const v = Config.colors.presets.variant ?? "";
				if (v === "")
					return "";
				return qsTr("%1%2").arg(v.charAt(0).toUpperCase()).arg(v.slice(1).toLowerCase());
			}
			label: qsTr("Variant")
			subtext: qsTr("Select preset variant")
			rootParent: root.flickable

			initialSelect: Config.colors.presets.variant

			onAccepted: {
				if (!selectedItem)
					return;

				const v = selectedItem.toLowerCase();
				const s = Config.colors.presets.name;
				const existingAccent = Config.colors.presets.accent;
				let a = "";

				if (existingAccent !== "" && adapter.presets[s].variants[v]?.accents.some(a => a === existingAccent))
					a = existingAccent;

				if (a !== "")
					Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`, "-a", `${a}`]);
				else
					Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`]);
			}
		}

		DialogSelectButton {
			settingAnchor: "colors-fonts-preset-accent"
			// qmlformat off
			model: {
				const a = adapter.presets[Config.colors.presets.name].variants[Config.colors.presets.variant]?.accents ?? [];

				if (a.length === 0)
					return a;

				const map = a.map(a => ({
					id: a,
					label: qsTr("%1%2")
						.arg(a.charAt(0).toUpperCase())
						.arg(a.slice(1).toLowerCase())
				}));

				return map;
			}
			// qmlformat on
			acceptLabel: qsTr("Confirm")
			enabled: !Config.colors.schemeGen && model.length > 1
			header: qsTr("Select accent")
			rowButton.activeItem: {
				const a = Config.colors.presets.accent ?? "";
				if (a === "")
					return "";
				return qsTr("%1%2").arg(a.charAt(0).toUpperCase()).arg(a.slice(1).toLowerCase());
			}
			label: qsTr("Accent")
			last: true
			subtext: qsTr("Select preset accent")
			rootParent: root.flickable

			initialSelect: Config.colors.presets.accent

			onAccepted: {
				if (!selectedItem)
					return;

				const a = selectedItem.toLowerCase();
				const v = Config.colors.presets.variant;
				const s = Config.colors.presets.name;

				Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${s}:${v}`, "-a", `${a}`]);
			}
		}

		SectionHeader {
			text: qsTr("Fonts")
		}

		SearchPopup {
			id: selectSansFont

			settingAnchor: "colors-fonts-sans-font"
			model: root.fonts
			acceptLabel: qsTr("Confirm")
			enabled: Object.keys(model).length > 0
			separateContent: false
			header: qsTr("Select font")
			first: true
			rowButton.activeItem: root.fonts.find(s => {
				var regex = new RegExp(Config.appearance.font.family.sans, "i");
				return regex.test(s);
			}) ?? ""
			label: qsTr("Sans font")
			subtext: qsTr("Select desired sans font")
			rootParent: root.flickable

			initialSelect: Config.appearance.font.family.sans

			onAccepted: {
				if (!selectedItem)
					return;

				Config.appearance.font.family.sans = selectedItem;
			}
		}

		SearchPopup {
			id: selectMonoFont

			acceptLabel: qsTr("Confirm")
			enabled: Object.keys(model).length > 0
			settingAnchor: "colors-fonts-mono-font"
			separateContent: false
			header: qsTr("Select font")
			rowButton.activeItem: root.fonts.find(s => {
				var regex = new RegExp(Config.appearance.font.family.mono, "i");
				return regex.test(s);
			}) ?? ""
			label: qsTr("Mono font")
			subtext: qsTr("Select desired mono font")
			model: root.fonts
			rootParent: root.flickable

			initialSelect: Config.appearance.font.family.mono

			onAccepted: {
				if (!selectedItem)
					return;

				Config.appearance.font.family.mono = selectedItem;
			}
		}

		SearchPopup {
			id: selectClockFont

			acceptLabel: qsTr("Confirm")
			enabled: Object.keys(model).length > 0
			separateContent: false
			settingAnchor: "colors-fonts-clock-font"
			header: qsTr("Select font")
			last: true
			rowButton.activeItem: root.fonts.find(s => {
				var regex = new RegExp(Config.appearance.font.family.clock, "i");
				return regex.test(s);
			}) ?? ""
			label: qsTr("Clock font")
			subtext: qsTr("Select desired clock font")
			model: root.fonts
			rootParent: root.flickable

			initialSelect: Config.appearance.font.family.clock

			onAccepted: {
				if (!selectedItem)
					return;

				Config.appearance.font.family.clock = selectedItem;
			}
		}
	}
}
