//! Dial-pad screen — compose a number and place a call. Reached from the
//! home FAB; the close button returns to the home screen.

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

use crate::app::Message;
use crate::palette;
use crate::types::ContactRef;
use crate::views::components as ui;

const KEYS: [ ( char, &str ); 12 ] =
[
	( '1', ""     ), ( '2', "ABC" ), ( '3', "DEF"  ),
	( '4', "GHI"  ), ( '5', "JKL" ), ( '6', "MNO"  ),
	( '7', "PQRS" ), ( '8', "TUV" ), ( '9', "WXYZ" ),
	( '*', ""     ), ( '0', "+"   ), ( '#', ""     ),
];

pub fn view( typed: &str, contacts: &[ ContactRef ] ) -> Element<Message>
{
	let palette = ltk::theme_palette();

	let header = container::<Message>(
		row::<Message>()
			.push( ui::round_icon_btn( "navigation/close", 22.0, palette.text_primary, Message::CloseDialpad ) )
			.push( spacer() )
			.push( container( ui::icon( "navigation/menu-kebab", 22.0, palette.text_primary ) ).padding( palette::dp( 9.0 ) ) )
	)
		.padding_h( palette::dp( 14.0 ) )
		.padding_top( palette::dp( 10.0 ) );

	let display = container::<Message>( number_display( typed, &palette ) )
		.padding_h( palette::dp( 24.0 ) )
		.padding_top( palette::dp( 16.0 ) )
		.padding_bottom( palette::dp( 8.0 ) );

	let suggestions = suggestion_list( typed, contacts );

	let mut grid = ltk::grid::<Message>( 3 ).spacing( palette::dp( 8.0 ) );
	for ( d, sub ) in KEYS
	{
		grid = grid.push( key( d, sub, &palette ) );
	}
	let keys = container::<Message>( grid ).padding_h( palette::dp( 26.0 ) );

	let body = column::<Message>()
		.push( header )
		.push( display )
		.push( suggestions )
		.push( spacer() )
		.push( keys )
		.push( call_row( typed, &palette ) );

	container::<Message>( body ).background( palette.surface ).into()
}

fn number_display( typed: &str, palette: &ltk::Palette ) -> Element<Message>
{
	if typed.is_empty()
	{
		return column::<Message>()
			.align_center_x( true )
			.push(
				text( "Dial a number" )
					.size( palette::dp( 22.0 ) )
					.weight( 300 )
					.color( palette::text_tertiary() )
			)
			.into();
	}

	let size = if typed.len() > 14 { 26.0 } else if typed.len() > 10 { 32.0 } else { 36.0 };

	column::<Message>()
		.align_center_x( true )
		.push( text( typed ).size( palette::dp( size ) ).color( palette.text_primary ).align_center() )
		.into()
}

fn suggestion_list( typed: &str, contacts: &[ ContactRef ] ) -> Element<Message>
{
	let q = digits_only( typed );

	let mut col = column::<Message>().spacing( palette::dp( 4.0 ) ).padding( palette::dp( 8.0 ) );
	if q.len() >= 2
	{
		for c in contacts.iter()
			.filter( |c| c.number.as_ref().is_some_and( |n| digits_only( n.as_str() ).contains( &q ) ) )
			.take( 3 )
		{
			col = col.push( ui::contact_row( c ) );
		}
	}
	col.into()
}

fn key( d: char, sub: &str, palette: &ltk::Palette ) -> Element<Message>
{
	let mut keypad = column::<Message>()
		.align_center_x( true )
		.push( text( d.to_string() ).size( palette::dp( 30.0 ) ).color( palette.text_primary ).align_center() );

	if !sub.is_empty()
	{
		keypad = keypad.push( text( sub ).size( palette::dp( 10.0 ) ).weight( 600 ).color( palette::text_tertiary() ).align_center() );
	}

	pressable( container( keypad ).padding_v( palette::dp( 16.0 ) ).padding_h( palette::dp( 24.0 ) ) )
		.on_press( Message::DialerDigit( d ) )
		.into()
}

fn call_row( typed: &str, palette: &ltk::Palette ) -> Element<Message>
{
	let call_icon = ui::icon( "communication/phone", 26.0, Color::WHITE );

	let call: Element<Message> = if typed.is_empty()
	{
		container::<Message>( call_icon )
			.background( palette::accept() )
			.radius( 34.0 )
			.padding( palette::dp( 21.0 ) )
			.opacity( 0.35 )
			.into()
	} else {
		pressable(
			container::<Message>( call_icon )
				.background( palette::accept() )
				.radius( 34.0 )
				.padding( palette::dp( 21.0 ) )
		)
			.on_press( Message::DialerCall )
			.into()
	};

	let backspace: Element<Message> = if typed.is_empty()
	{
		spacer().width( palette::dp( 56.0 ) ).into()
	} else {
		ui::round_icon_btn( "keyboard/backspace", 24.0, palette.text_secondary, Message::DialerBackspace )
	};

	container::<Message>(
		row::<Message>()
			.push( spacer().width( palette::dp( 56.0 ) ) )
			.push( spacer() )
			.push( call )
			.push( spacer() )
			.push( backspace )
	)
		.padding_h( palette::dp( 22.0 ) )
		.padding_top( palette::dp( 18.0 ) )
		.padding_bottom( palette::dp( 36.0 ) )
		.into()
}

fn digits_only( s: &str ) -> String
{
	s.chars().filter( |c| c.is_ascii_digit() ).collect()
}
