use crate::ui::prelude::*;
use crate::network;

pub( crate ) const WIFI_PASSWORD_ID: ltk::WidgetId = ltk::WidgetId( "wifi/password" );

pub( crate ) fn view_wifi( state: &State ) -> Element<Msg>
{
	let mut col = column::<Msg>()
		.padding( 24.0 )
		.spacing( 4.0 )
		.push( header( &tr!( "home.wifi" ) ) )
		.push( toggle_row( tr!( "home.wifi" ), state.wifi_on, Msg::ToggleWifi ) );

	if state.wifi_on && state.connectivity == network::CONNECTIVITY_PORTAL
	{
		let it = list_item( tr!( "wifi.sign_in" ) )
			.subtitle( tr!( "wifi.sign_in_sub" ) )
			.on_press( Msg::OpenPortal );
		col = col.push( with_chevron( it ) );
	}

	if state.wifi_on
	{
		col = col.push( separator() );

		// The connected network never waits for scan results: while the
		// first scan is still running it is synthesised from the known
		// SSID, and start_wifi_scan keeps the real entry across rescans.
		let has_connected = state.wifi_networks.iter().any( |n| n.connected );
		if has_connected
		{
			for net in &state.wifi_networks
			{
				if !net.connected { continue; }
				col = col.push( wifi_network_row( state, net ) );
				if state.wifi_selected.as_deref() == Some( net.ssid.as_str() )
				{
					col = col.push( wifi_network_actions( state, net ) );
				}
			}
		} else if let Some( ssid ) = state.connected_ssid.as_deref() {
			let ( rgba, w, h ) = status_dot( StatusDot::Active );
			let it = list_item( ssid )
				.subtitle( tr!( "common.connected" ) )
				.trailing_icon( rgba, w, h );
			col = col.push( with_icon( it, "system/wifi-signal-full" ) );
		}

		col = col.push(
			row::<Msg>()
				.push( t_sec!( tr!( "wifi.available" ) ).size( 13.0 ) )
				.push( spacer() )
				.push( refresh_button( state.wifi_scanning, Msg::WifiScan ) )
		);
		col = col.push( spacer().height( 8.0 ) );

		if state.wifi_scanning
		{
			col = col.push( scanning_row( state.started_at.elapsed().as_secs_f32() ) );
		} else {
			let mut net_col = column::<Msg>().padding( 0.0 ).spacing( 0.0 );
			let mut found   = false;
			for net in &state.wifi_networks
			{
				if net.connected { continue; }
				found   = true;
				net_col = net_col.push( wifi_network_row( state, net ) );
				if state.wifi_selected.as_deref() == Some( net.ssid.as_str() )
				{
					net_col = net_col.push( wifi_network_actions( state, net ) );
				}
			}
			if found
			{
				// The vertical scroll claims all remaining space, like a
				// spacer — adding one after it would halve the viewport.
				return col.push( scroll( net_col ) ).into();
			}
			col = col.push( t_sec!( tr!( "wifi.none_found" ) ).size( 13.0 ) );
		}
	}

	col.push( spacer() ).into()
}

fn wifi_network_row( state: &State, net: &network::WifiNetwork ) -> Element<Msg>
{
	let signal = format!( "{}%", net.signal );
	let subtitle =
		if state.wifi_connecting.as_deref() == Some( net.ssid.as_str() ) { tr!( "common.connecting" ) }
		else if net.connected { tr!( "common.connected" ) }
		else if net.known     { tr!( "wifi.saved" ) }
		else if net.secured   { tr!( "wifi.secured" ) }
		else                  { tr!( "wifi.open" ) };
	let dot =
		if net.connected  { StatusDot::Active }
		else if net.known { StatusDot::Known }
		else              { StatusDot::None };
	let ( rgba, w, h ) = status_dot( dot );
	let mut it = list_item( &net.ssid )
		.subtitle( subtitle )
		.trailing( &signal )
		.trailing_icon( rgba, w, h )
		.on_press( Msg::SelectWifi( net.ssid.clone() ) );
	if let Some( ( rgba, w, h ) ) = wifi_icon( net.signal )
	{
		it = it.icon( rgba, w, h );
	}
	it.into()
}

fn wifi_network_actions( state: &State, net: &network::WifiNetwork ) -> Element<Msg>
{
	let mut col = column::<Msg>().spacing( 8.0 ).padding( 8.0 );

	if state.wifi_error.as_deref() == Some( net.ssid.as_str() )
	{
		col = col.push( t_sec!( tr!( "wifi.could_not_connect" ) ).size( 13.0 ) );
	}

	let needs_password = net.secured && !net.known && !net.connected;
	if needs_password
	{
		col = col.push(
			text_edit( tr!( "wifi.password" ), &state.wifi_password )
				.id( WIFI_PASSWORD_ID )
				.secure( !state.wifi_pw_visible )
				.password_toggle( state.wifi_pw_visible, Msg::ToggleWifiPasswordVisible )
				.on_change( Msg::WifiPasswordInput )
				.on_submit( Msg::WifiConnect )
		);
	}

	let mut buttons = row::<Msg>().spacing( 8.0 );
	if !net.connected
	{
		let mut connect = button( tr!( "common.connect" ) );
		if state.wifi_connecting.is_none() && ( !needs_password || !state.wifi_password.is_empty() )
		{
			connect = connect.on_press( Msg::WifiConnect );
		}
		buttons = buttons.push( connect );
	}
	if net.known || net.connected
	{
		buttons = buttons.push(
			button( tr!( "common.forget" ) )
				.variant( ButtonVariant::Tertiary )
				.on_press( Msg::WifiForget( net.ssid.clone() ) )
		);
	}

	col.push( buttons ).into()
}
