// Monitors panel: mirror/extend mode, per-screen scale, resolution and
// placement, over forge's list_outputs / set_output_config IPC.

use crate::system;
use crate::ui::prelude::*;

pub( crate ) fn view_monitors( state: &State ) -> Element<Msg>
{
	let mut col = column::<Msg>()
		.padding( 24.0 )
		.spacing( 12.0 )
		.push( header( &tr!( "home.monitors" ) ) );

	if state.outputs.is_empty()
	{
		let key = if state.monitors_scanning { "monitors.scanning" } else { "monitors.none_found" };
		col = col.push( t_sec!( tr!( key ) ).size( 13.0 ) );
		return col.push( spacer() ).into();
	}

	// ── Session mode ────────────────────────────────────────────────────
	if state.outputs.len() > 1
	{
		col = col.push( t_sec!( tr!( "monitors.mode" ) ).size( 13.0 ) );
		col = col.push(
			row::<Msg>()
				.spacing( 6.0 )
				.push( seg_btn( &tr!( "monitors.extend" ), state.display_extend,  Msg::SetDisplayExtend( true )  ) )
				.push( seg_btn( &tr!( "monitors.mirror" ), !state.display_extend, Msg::SetDisplayExtend( false ) ) )
		);
		col = col.push( section_sep() );
	}

	// ── Arrangement strip: tiles ordered left-to-right as on the desk ───
	if state.display_extend && state.outputs.len() > 1
	{
		let mut ordered: Vec<&system::Output> = state.outputs.iter().collect();
		ordered.sort_by_key( |o| o.position.unwrap_or( ( i32::MAX, i32::MAX ) ) );
		let mut strip = row::<Msg>().spacing( 6.0 );
		for o in ordered
		{
			let selected = state.monitor_selected.as_deref() == Some( o.connector.as_str() );
			strip = strip.push( seg_btn( &monitor_title( o ), selected, Msg::SelectMonitor( o.connector.clone() ) ) );
		}
		col = col.push( strip );
		col = col.push( section_sep() );
	}

	// ── Per-monitor list with the selected one expanded ─────────────────
	let mut combo_popup: Option<Element<Msg>> = None;
	for o in &state.outputs
	{
		let selected = state.monitor_selected.as_deref() == Some( o.connector.as_str() );
		let mut item = list_item( monitor_title( o ) )
			.subtitle( system::mode_label( &o.current_mode ) )
			.on_press( Msg::SelectMonitor( o.connector.clone() ) );
		if o.primary
		{
			item = item.trailing( tr!( "monitors.primary" ) );
		}
		else if !o.enabled
		{
			item = item.trailing( tr!( "monitors.disabled" ) );
		}
		col = col.push( item );

		if selected
		{
			let ( section, popup ) = monitor_detail( state, o );
			col = col.push( section );
			combo_popup = popup;
		}
	}

	// The popup layers over the page from the same surface.
	let mut s = stack::<Msg>().push( scroll( col.push( spacer() ) ) );
	if let Some( p ) = combo_popup { s = s.push( p ); }
	s.into()
}

fn monitor_title( o: &system::Output ) -> String
{
	if o.model.is_empty()
	{
		o.connector.clone()
	} else {
		format!( "{} ({})", o.model, o.connector )
	}
}

fn monitor_detail( state: &State, o: &system::Output ) -> ( Element<Msg>, Option<Element<Msg>> )
{
	let mut col = column::<Msg>()
		.padding( 12.0 )
		.spacing( 8.0 );

	// ── Scale: automatic toggle + stepped slider, like Accessibility ────
	let auto     = o.scale <= 0.0;
	let auto_pct = ( o.auto_scale * 100.0 ).round() as u32;
	col = col.push(
		toggle( auto )
			.label( tr!( "monitors.scale_auto", pct = auto_pct ) )
			.on_toggle( Msg::MonitorToggleScaleAuto )
	);
	if !auto
	{
		let shown = state.monitor_scale_drag.unwrap_or( o.scale as f32 );
		let last  = ( system::INTERFACE_STEPS.len() - 1 ) as f32;
		let norm  = system::interface_step_index( shown ) as f32 / last;
		col = col.push(
			t_sec!( tr!( "monitors.scale", pct = ( shown * 100.0 ).round() as u32 ) ).size( 13.0 )
		);
		col = col.push(
			slider( norm.clamp( 0.0, 1.0 ) )
				.on_change( |v| Msg::MonitorPreviewScale( system::interface_step_at( v ) ) )
				.on_release( |v| Msg::MonitorSetScale( system::interface_step_at( v ) ) )
		);
	}

	// ── Resolution ──────────────────────────────────────────────────────
	let combo_w = combo(
		state.monitor_mode_combo.clone(),
		o.modes.iter().map( |m| system::mode_label( m ) ).collect(),
	)
		.label( tr!( "monitors.resolution" ) )
		.on_toggle_open( Msg::MonitorModeToggle )
		.on_select_idx( Msg::MonitorModeSelect )
		.on_dismiss( Msg::MonitorModeDismiss );
	col = col.push( combo_w.trigger() );
	let popup = combo_w.popup();

	// ── Placement and enable, externals in extend only ──────────────────
	if state.display_extend && !o.primary
	{
		col = col.push( t_sec!( tr!( "monitors.placement" ) ).size( 13.0 ) );
		let primary_size = state.outputs.iter()
			.find( |p| p.primary )
			.and_then( |p| p.logical_size )
			.unwrap_or( ( 1, 1 ) );
		let place = system::placement_of( o.position, primary_size );
		use system::Placement;
		col = col.push(
			row::<Msg>()
				.spacing( 6.0 )
				.push( seg_btn( &tr!( "monitors.place_left" ),  place == Placement::Left,  Msg::MonitorPlace( Placement::Left )  ) )
				.push( seg_btn( &tr!( "monitors.place_right" ), place == Placement::Right, Msg::MonitorPlace( Placement::Right ) ) )
				.push( seg_btn( &tr!( "monitors.place_above" ), place == Placement::Above, Msg::MonitorPlace( Placement::Above ) ) )
				.push( seg_btn( &tr!( "monitors.place_below" ), place == Placement::Below, Msg::MonitorPlace( Placement::Below ) ) )
		);
		col = col.push(
			toggle( o.enabled )
				.label( tr!( "monitors.enabled" ) )
				.on_toggle( Msg::MonitorEnable( !o.enabled ) )
		);
	}

	( col.into(), popup )
}
