//! Desktop-specific QS chrome — the top row stacks the WiFi + BT
//! chips on the left half against a single full-height media card on
//! the right, and the middle stripe replaces the vslider pair with
//! two horizontal slider pills. The round-button bank (re-used from
//! `super::buttons`) is identical to the portrait variant.
//!
//! Sized against the same canonical `grid_row_h` and `VSLIDER_H`
//! primitives the portrait branch derives its geometry from, so the
//! desktop layout's overall height stays predictable for the
//! `desktop_panel_height` helper in `super::super`.

use std::sync::Arc;

use crate::message::Message;
use crate::mpris::MediaState;
use crate::system::SystemState;

use rust_i18n::t;

use super::super::icons::Icons;
use super::super::{ desktop_panel_width, CARD_ICON_PX, CARD_PADDING_H, CARD_RADIUS, GRID_GAP, PANEL_OUTER_PAD, VSLIDER_W };

fn desktop_card_inner(
	icons:     &super::super::icons::Icons,
	icon_slot: &Option<( std::sync::Arc<Vec<u8>>, u32, u32 )>,
	title:     impl Into<String>,
	status:    impl Into<String>,
	palette:   &ltk::Palette,
	pad_v:     f32,
	k:         f32,
) -> ltk::Element<super::super::super::message::Message>
{
	use super::super::super::message::Message;
	// `k` folds density and short-screen compaction (see
	// `desktop_pill_factor`); fonts resolve in logical space and get the
	// density applied at raster, so they only take the compaction part.
	let font_k = k / ltk::density().max( 1.0 );
	let icon_el: ltk::Element<Message> = match icon_slot
	{
		Some( ( raw, w, h ) ) =>
		{
			let tinted = icons.tint_cached( raw, palette.text_primary );
			ltk::img_widget( tinted, *w, *h ).size( CARD_ICON_PX * k, CARD_ICON_PX * k ).into()
		}
		None => ltk::spacer().into(),
	};
	ltk::container::<Message>(
		ltk::row::<Message>()
			.spacing( 6.0 * k )
			.padding( 0.0 )
			.push( ltk::spacer().width( 8.0 * k ) )
			.push( icon_el )
			.push( ltk::flex(
				ltk::column::<Message>()
					.padding( 0.0 )
					.spacing( 2.0 * k )
					.push( ltk::text( title.into()  ).size( 12.0 * font_k ).color( palette.text_primary ) )
					.push( ltk::text( status.into() ).size( 10.0 * font_k ).color( palette.text_secondary ) ),
			) )
			.push( ltk::spacer().width( 8.0 * k ) ),
	)
	.surface( "surface-card-flat" )
	.radius( CARD_RADIUS * k )
	.padding_h( CARD_PADDING_H * k )
	.padding_v( pad_v )
	.into()
}
use super::middle;

/// Top row: column of (WiFi chip, BT chip) on the left half + a
/// full-height media card on the right. Both halves preferred-height
/// to `VSLIDER_H` (the chips column comes out to `2 × grid_row_h +
/// GRID_GAP` which equals `VSLIDER_H` by construction; the media card
/// already self-pads to `VSLIDER_H` regardless of MPRIS state). Width
/// split is 50/50 via two `flex` siblings — same idiom the portrait
/// middle row uses for its own 50/50 split.
pub( super ) fn top_row(
	icons:        &Icons,
	system_state: &SystemState,
	media_state:  Option<&MediaState>,
	palette:      &ltk::Palette,
	grid_row_h:   f32,
	k:            f32,
) -> ltk::Element<Message>
{
	let chips_column = chips_stacked( icons, system_state, palette, grid_row_h, k );
	// Desktop keeps the design's fixed px sizes: resolving the card's
	// vw fractions against the 480 px reference width reproduces them.
	// The reference follows the pill factor so the card's internal
	// geometry doubles on a scale-2 output and shrinks with the
	// short-screen compaction alongside the rest of the pill.
	let card_w       = ( desktop_panel_width() - 2.0 * PANEL_OUTER_PAD - GRID_GAP ) * k / 2.0;
	let media        = middle::media_card( icons, media_state, palette, grid_row_h, 480.0 * k, card_w );

	ltk::row::<Message>()
		.padding( 0.0 )
		.spacing( GRID_GAP * k )
		.fill_height()
		.push( ltk::flex( chips_column ) )
		.push( ltk::flex( media ) )
		.into()
}

/// Two chip cards stacked vertically with `GRID_GAP` between them —
/// WiFi on top with the SSID / connection status, Bluetooth below
/// with the connected / enabled / disabled triple-state mirroring the
/// WiFi pattern. Each chip is the same `surface-card-flat` envelope
/// the portrait chip row uses, just composed in a column instead of a
/// 2-column grid.
fn chips_stacked(
	icons:        &Icons,
	system_state: &SystemState,
	palette:      &ltk::Palette,
	grid_row_h:   f32,
	k:            f32,
) -> ltk::Element<Message>
{
	let card_pad_v = ( ( grid_row_h - 24.0 * k ) / 2.0 ).max( 0.0 );

	let wifi_label = t!( "qs_wifi" ).to_string();
	let ( wifi_title, wifi_status ) = if system_state.wifi.connected
	{
		(
			system_state.wifi.ssid.clone().unwrap_or_else( || wifi_label.clone() ),
			t!( "qs_status_connected" ).to_string(),
		)
	} else if system_state.wifi.enabled {
		( wifi_label.clone(), t!( "qs_status_on" ).to_string() )
	} else {
		( wifi_label.clone(), t!( "qs_status_off" ).to_string() )
	};

	let bt_status = if system_state.bluetooth.connected
	{
		t!( "qs_status_connected" ).to_string()
	} else if system_state.bluetooth.enabled {
		t!( "qs_status_on" ).to_string()
	} else {
		t!( "qs_status_off" ).to_string()
	};

	let wifi_card = ltk::pressable(
		desktop_card_inner( icons, &icons.wifi_card, &wifi_title, wifi_status, palette, card_pad_v, k ),
	)
	.on_press( Message::OpenWifiSettings );

	let bt_card = ltk::pressable(
		desktop_card_inner( icons, &icons.bluetooth, t!( "qs_bluetooth" ).to_string(), bt_status, palette, card_pad_v, k ),
	)
	.on_press( Message::OpenBluetoothSettings );

	ltk::column::<Message>()
		.padding( 0.0 )
		.spacing( GRID_GAP * k )
		.push( wifi_card )
		.push( bt_card )
		.into()
}

// ─── horizontal slider pills ────────────────────────────────────────────────

/// Pill height of each horizontal slider. Matches the round-button
/// diameter (`VSLIDER_W`) so the sliders stripe and the round-button
/// stripe below it land on the same vertical rhythm.
const HSLIDER_PILL_H: f32 = VSLIDER_W;

/// Stacked slider pills — brightness on top, volume below. Each pill
/// is a `surface-card-flat` envelope wrapping a `column( title,
/// row( min_icon, slider, max_icon ) )`, with the `Slider` widget
/// itself (from ltk) flex-claiming the middle of the row.
pub( super ) fn sliders(
	icons:        &Icons,
	system_state: &SystemState,
	palette:      &ltk::Palette,
	k:            f32,
) -> ltk::Element<Message>
{
	let bright_value = system_state.brightness          as f32 / 100.0;
	let vol_value    = system_state.audio.volume        as f32 / 100.0;

	let display_label = t!( "qs_display" ).to_string();
	let sound_label   = t!( "qs_sound"   ).to_string();
	let bright_pill = slider_pill(
		icons,
		&display_label,
		bright_value,
		Message::SetBrightness,
		&icons.brightness_slider_low,
		&icons.brightness_slider,
		palette,
		k,
	);
	let vol_pill = slider_pill(
		icons,
		&sound_label,
		vol_value,
		Message::SetVolume,
		&icons.speaker_slider_mute,
		&icons.speaker_slider,
		palette,
		k,
	);

	ltk::column::<Message>()
		.padding( 0.0 )
		.spacing( GRID_GAP * k )
		.push( bright_pill )
		.push( vol_pill )
		.into()
}

fn slider_pill(
	icons:        &Icons,
	title:        &str,
	value:        f32,
	on_change:    fn( f32 ) -> Message,
	icon_min:     &Option<( Arc<Vec<u8>>, u32, u32 )>,
	icon_max:     &Option<( Arc<Vec<u8>>, u32, u32 )>,
	palette:      &ltk::Palette,
	k:            f32,
) -> ltk::Element<Message>
{
	let d      = ltk::density().max( 1.0 );
	let pill_h = HSLIDER_PILL_H * k;
	let title_text = ltk::text( title.to_string() )
		.size( 14.0 * k / d )
		.color( palette.text_primary );

	let icon_left  = slider_glyph( icons, icon_min, palette, k );
	let icon_right = slider_glyph( icons, icon_max, palette, k );

	// Slider chrome opts into the panel's glass slot family
	// (`surface-slider-track-flat` / `surface-slider-fill-flat`,
	// without the per-instance backdrop blur because the panel-wide
	// chrome already runs one) and the EYDOS accent thumb (cyan
	// inner + 4 px white ring) so the pill matches the Figma desktop
	// QS slider verbatim instead of falling back to the default
	// flat-colour track + white thumb.
	let track = ltk::slider( value )
		.on_change( on_change )
		.track_surface( "surface-slider-track-flat" )
		.fill_surface( "surface-slider-fill-flat" )
		.accent_thumb( true );

	let track_row = ltk::row::<Message>()
		.padding( 0.0 )
		.spacing( 10.0 * k )
		.push( icon_left )
		.push( ltk::flex( track ) )
		.push( icon_right );

	let inner = ltk::column::<Message>()
		.padding( 0.0 )
		.spacing( 4.0 * k )
		.push( title_text )
		.push( track_row );

	// Vertical pad fills the rest of `pill_h` after the title and
	// slider widget take their natural heights — keeps the pill's
	// outer footprint locked at the (compacted) canonical `VSLIDER_W`
	// so the `desktop_panel_height` row math stays valid.
	let title_h   = 20.0 * k;
	let inner_gap = 4.0 * k;
	let slider_h  = 36.0 * d; // ltk::widget::slider::theme::HEIGHT — stock, uncompacted
	let content_h = title_h + inner_gap + slider_h;
	let pad_v     = ( ( pill_h - content_h ) / 2.0 ).max( 0.0 );

	ltk::container::<Message>( inner )
		.surface( "surface-card-flat" )
		.radius( CARD_RADIUS * k )
		.padding_h( CARD_PADDING_H * k )
		.padding_v( pad_v )
		.into()
}

fn slider_glyph(
	icons:     &Icons,
	icon_slot: &Option<( Arc<Vec<u8>>, u32, u32 )>,
	palette:   &ltk::Palette,
	k:         f32,
) -> ltk::Element<Message>
{
	let px = 18.0 * k;
	match icon_slot
	{
		Some( ( raw, w, h ) ) =>
		{
			let tinted = icons.tint_cached( raw, palette.text_primary );
			ltk::img_widget( tinted, *w, *h ).size( px, px ).into()
		}
		None => ltk::Element::<Message>::from( ltk::spacer().width( px ).height( px ) ),
	}
}
