// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>

//! Theme preference / mode types and per-asset specification structs.

use std::path::PathBuf;

use serde::{ Deserialize, Serialize };

use crate::types::Color;

// ─── Wallpaper / launcher ────────────────────────────────────────────────────

/// How a wallpaper image is fitted to its surface.
#[ derive( Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize ) ]
#[ serde( rename_all = "kebab-case" ) ]
pub enum WallpaperFit
{
	/// Scale uniformly to fill the surface, cropping the overflow.
	Cover,
	/// Scale uniformly to fit inside the surface, letterboxing if needed.
	Contain,
	/// Scale non-uniformly to exactly match the surface.
	Stretch,
	/// Place at original size centered on the surface.
	Center,
	/// Repeat the image at original size to cover the surface.
	Tile,
}

impl Default for WallpaperFit
{
	fn default() -> Self { WallpaperFit::Cover }
}

/// Wallpaper backing for a single theme variant.
#[ derive( Debug, Clone ) ]
pub struct WallpaperSpec
{
	/// Absolute path to the image, or `None` for the built-in fallback that
	/// just paints [`crate::theme::Palette::bg`].
	pub path: Option<PathBuf>,
	pub fit:  WallpaperFit,
}

/// Styling for the application launcher surface.
#[ derive( Debug, Clone, Copy ) ]
pub struct LauncherSpec
{
	/// Background fill of the launcher panel.
	pub background:    Color,
	/// Outer corner radius of the launcher panel, in CSS pixels.
	pub border_radius: f32,
}

/// Styling for compositor / window-decoration controls.
#[ derive( Debug, Clone, Copy ) ]
pub struct WindowControlsSpec
{
	/// Background fill of the SSD title bar strip the controls sit on.
	pub bar_bg:         Color,
	/// Symbol colour for minimize / maximize / restore / close glyphs.
	pub icon:           Color,
	/// Button background while hovered.
	pub hover_bg:       Color,
	/// Button background while pressed.
	pub pressed_bg:     Color,
	/// Close-button background while hovered.
	pub close_hover_bg: Color,
	/// Close-button symbol colour while hovered.
	pub close_icon:     Color,
	/// Keyboard focus ring colour.
	pub focus_ring:     Color,
}

// ─── Mode and preference ─────────────────────────────────────────────────────

/// Which of the two variants a theme family resolves to.
#[ derive( Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize ) ]
#[ serde( rename_all = "kebab-case" ) ]
pub enum ThemeMode
{
	Light,
	Dark,
}

impl Default for ThemeMode
{
	fn default() -> Self { ThemeMode::Light }
}

impl ThemeMode
{
	/// Auto-select light or dark from the local hour of day.
	///
	/// Dark is used between 19:00 and 06:59 local time, light otherwise.
	/// `hour` must be in `0..=23`.
	pub const fn from_hour( hour: u32 ) -> Self
	{
		if hour >= 19 || hour < 7 { ThemeMode::Dark } else { ThemeMode::Light }
	}
}

/// Shell-side persisted preference. `Auto` is resolved to a [`ThemeMode`]
/// before reaching ltk — the toolkit itself only knows about Light and Dark.
#[ derive( Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize ) ]
#[ serde( rename_all = "kebab-case" ) ]
pub enum ThemePreference
{
	Light,
	Dark,
	Auto,
}

impl Default for ThemePreference
{
	fn default() -> Self { ThemePreference::Auto }
}

impl ThemePreference
{
	/// Resolve to a concrete mode given the current local hour `[0, 23]`.
	pub const fn resolve( self, hour: u32 ) -> ThemeMode
	{
		match self
		{
			ThemePreference::Light => ThemeMode::Light,
			ThemePreference::Dark  => ThemeMode::Dark,
			ThemePreference::Auto  => ThemeMode::from_hour( hour ),
		}
	}
}

#[ cfg( test ) ]
mod tests
{
	use super::*;

	#[ test ]
	fn preference_resolves_auto_by_hour()
	{
		assert_eq!( ThemePreference::Auto.resolve(  3 ), ThemeMode::Dark );
		assert_eq!( ThemePreference::Auto.resolve( 12 ), ThemeMode::Light );
		assert_eq!( ThemePreference::Auto.resolve( 22 ), ThemeMode::Dark );
		assert_eq!( ThemePreference::Light.resolve( 22 ), ThemeMode::Light );
	}
}
