//! In-call screen — visible while a call is dialing, ringing outbound,
//! accepting, or active.

use std::time::Instant;

use ltk::
{
	column, container, pressable, row, spacer, text,
	Element,
};

use crate::app::Message;
use crate::palette;
use crate::types::{ Call, CallState, ContactRef };
use crate::views::components as ui;

const DTMF_DIGITS: [ char; 12 ] =
[
	'1', '2', '3',
	'4', '5', '6',
	'7', '8', '9',
	'*', '0', '#',
];

pub fn view( call: &Call, contact: Option<&ContactRef>, dtmf_open: bool ) -> Element<Message>
{
	let palette = ltk::theme_palette();

	let title = match contact
	{
		Some( c ) => c.display_name.clone(),
		None      => call.number.as_str().to_string(),
	};

	let status = match call.state
	{
		CallState::Dialing   => "Calling…".to_string(),
		CallState::Ringing   => "Ringing…".to_string(),
		CallState::Accepting => "Connecting…".to_string(),
		CallState::Active    => format_elapsed( call.since ),
		CallState::Hanging   => "Hanging up…".to_string(),
		CallState::Ended( _ ) => "Call ended".to_string(),
	};

	let header = column::<Message>()
		.align_center_x( true )
		.spacing( palette::dp( 14.0 ) )
		.push( ui::avatar( contact, 112.0 ) )
		.push( text( title ).size( palette::dp( 26.0 ) ).weight( 600 ).color( palette.text_primary ).align_center() )
		.push( text( call.number.as_str().to_string() ).size( palette::dp( 13.0 ) ).color( palette.text_secondary ).align_center() )
		.push( text( status ).size( palette::dp( 14.0 ) ).color( palette.text_secondary ).align_center() );

	let mic_icon = if call.muted { "hardware/microphone-muted" } else { "hardware/microphone" };
	let spk_icon = if call.speaker { "hardware/speaker-high" } else { "hardware/speaker-low" };

	let controls = row::<Message>()
		.push( spacer() )
		.push( toggle_btn( mic_icon, call.muted, Message::ToggleMute, &palette ) )
		.push( spacer() )
		.push( toggle_btn( spk_icon, call.speaker, Message::ToggleSpeaker, &palette ) )
		.push( spacer() )
		.push( toggle_btn( "communication/dial-pad", dtmf_open, Message::ToggleDtmfPad, &palette ) )
		.push( spacer() );

	let mut layout = column::<Message>()
		.padding( palette::dp( 24.0 ) )
		.spacing( palette::dp( 24.0 ) )
		.push( spacer() )
		.push( header )
		.push( spacer() )
		.push( controls );

	if dtmf_open
	{
		let mut grid = ltk::grid::<Message>( 3 ).spacing( palette::dp( 8.0 ) );
		for d in DTMF_DIGITS
		{
			grid = grid.push(
				pressable(
					container( text( d.to_string() ).size( palette::dp( 24.0 ) ).color( palette.text_primary ).align_center() )
						.padding_v( palette::dp( 12.0 ) )
						.padding_h( palette::dp( 20.0 ) )
				)
					.on_press( Message::DtmfDigit( d ) )
			);
		}
		layout = layout.push( container( grid ).padding_h( palette::dp( 26.0 ) ) );
	}

	let hangup = row::<Message>()
		.push( spacer() )
		.push( ui::circle_action( "communication/phone-reject", palette::danger(), Message::Hangup ) )
		.push( spacer() );

	container::<Message>(
		layout
			.push( spacer() )
			.push( hangup )
			.push( spacer().height( palette::dp( 24.0 ) ) )
	)
		.background( palette.surface )
		.into()
}

fn toggle_btn( icon_name: &str, active: bool, msg: Message, palette: &ltk::Palette ) -> Element<Message>
{
	let ( bg, fg ) = if active
	{
		( palette.accent, ui::ON_ACCENT )
	} else {
		( palette::chip(), palette.text_primary )
	};

	pressable(
		container( ui::icon( icon_name, 24.0, fg ) )
			.background( bg )
			.radius( 28.0 )
			.padding( palette::dp( 16.0 ) )
	)
		.on_press( msg )
		.into()
}

fn format_elapsed( since: Instant ) -> String
{
	let secs = since.elapsed().as_secs();
	format!( "{:02}:{:02}", secs / 60, secs % 60 )
}
