use std::sync::Arc;

pub type Image = ( Arc<Vec<u8>>, u32, u32 );

#[ derive( Debug, Clone, Copy, PartialEq, Eq ) ]
pub enum Mode
{
	/// Boot login: identify an arbitrary user and create a session.
	Greeter,
	/// Session lock: verify the current user to dismiss.
	Lock,
}

#[ derive( Debug, Clone, Copy, PartialEq, Eq ) ]
pub enum UnlockMethod
{
	Password,
	Pin,
	Gesture,
	Fingerprint,
}

#[ derive( Debug, Clone, Copy ) ]
pub struct Battery
{
	pub percent:  u8,
	pub charging: bool,
}

pub struct State
{
	pub mode:           Mode,
	pub method:         UnlockMethod,
	pub username:       String,
	pub secret:         String,
	pub error:          Option<String>,
	pub authenticating: bool,
	pub drag_progress:  f32,
	pub now:            chrono::DateTime<chrono::Local>,
	pub battery:        Option<Battery>,
	pub logo:           Option<Image>,
	pub shutdown_icon:  Option<Image>,
	pub reboot_icon:    Option<Image>,
	pub allow_shutdown: bool,
	pub allow_reboot:   bool,
	pub wallpaper:      Option<ltk::WallpaperBundle>,
	pub lockscreen_wp:  Option<ltk::WallpaperBundle>,
	pub surface_w:      u32,
	pub surface_h:      u32,
	pub revealed:       bool,
	pub swipe_up:       Option<Image>,
	available:          Vec<UnlockMethod>,
}

impl State
{
	pub fn new( available: Vec<UnlockMethod> ) -> Self
	{
		let method = available.first().copied().unwrap_or( UnlockMethod::Password );
		Self
		{
			mode:           Mode::Lock,
			method,
			username:       String::new(),
			secret:         String::new(),
			error:          None,
			authenticating: false,
			drag_progress:  0.0,
			now:            chrono::Local::now(),
			battery:        None,
			logo:           None,
			shutdown_icon:  None,
			reboot_icon:    None,
			allow_shutdown: false,
			allow_reboot:   false,
			wallpaper:      None,
			lockscreen_wp:  None,
			surface_w:      0,
			surface_h:      0,
			revealed:       false,
			swipe_up:       None,
			available,
		}
	}

	pub fn available( &self ) -> &[ UnlockMethod ] { &self.available }

	pub fn set_drag_progress( &mut self, p: f32 ) { self.drag_progress = p.clamp( 0.0, 1.0 ); }

	pub fn tick_clock( &mut self ) { self.now = chrono::Local::now(); }

	pub fn set_battery( &mut self, b: Option<Battery> ) { self.battery = b; }
}
