// Screen identifiers and the linear flow that ties them together.
//
// The installer is essentially a guided wizard with a few branches
// (Proton vs. local storage, Fingerprint sub-flow, two distinct
// tutorials at the end). Keeping all transitions in one file makes the
// flow auditable from a single place; screen modules only need to know
// which `Screen` they are and emit `Msg::Next` / `Msg::Back`.
//
// The wizard covers two disjoint scenarios selected by
// `state.mode` (see [`WizardMode`]): Install shows only the disk /
// copy screens, Configure only the personalisation ones. Both share
// the front page, language picker, welcome and finish screens.

use crate::state::{ State, StorageProvider, WizardMode };

#[ derive( Clone, Copy, Debug, PartialEq, Eq ) ]
pub enum Screen
{
	FrontPage,
	SelectLanguage,
	Welcome,

	// ── Wizard core (dot indicator visible) ─────────────────────────
	DiskManagement,
	Account,
	Wireless,
	Navigation,
	DataStorage,
	DataStorageProton,
	Permissions,
	SecuritySelector,
	SecurityFingerprintRegister,
	SecurityFingerprintDone,

	// ── Outro ───────────────────────────────────────────────────────
	InstallProgress,
	InstallFinish,

	// `step` is 0..=3: 0 is the intro card, 1..=3 are the numbered
	// gesture / smartcast steps.
	TutorialGestures( u8 ),
	TutorialSmartcast( u8 ),

	Done,
}

impl Screen
{
	/// The wizard-core screens that show the dot indicator, for the
	/// Configure flow. Returns `Some( ( current_0_indexed, total ) )`
	/// for those, and `None` for everything else — including the whole
	/// Install flow, which only has one wizard screen and would render
	/// a meaningless indicator.
	pub fn dot_indicator( self, mode: WizardMode ) -> Option<( usize, usize )>
	{
		if mode == WizardMode::Install { return None; }
		let total = 6;
		let idx = match self
		{
			Screen::Welcome                     => 0,
			Screen::Wireless                    => 1,
			Screen::Navigation                  => 2,
			Screen::DataStorage
			| Screen::DataStorageProton         => 3,
			Screen::Permissions                 => 4,
			Screen::SecuritySelector
			| Screen::SecurityFingerprintRegister
			| Screen::SecurityFingerprintDone   => 5,
			_ => return None,
		};
		Some( ( idx, total ) )
	}

	/// Tutorials use a tiny two-dot indicator (intro / numbered step
	/// vs. the rest). Returns `Some( ( idx, total ) )` for the
	/// tutorial screens and `None` otherwise.
	pub fn tutorial_dots( self ) -> Option<( usize, usize )>
	{
		match self
		{
			Screen::TutorialGestures( 0 )
			| Screen::TutorialSmartcast( 0 ) => Some( ( 0, 2 ) ),
			Screen::TutorialGestures( _ )
			| Screen::TutorialSmartcast( _ ) => Some( ( 1, 2 ) ),
			_ => None,
		}
	}
}

/// Compute the next screen given the current one and the user state.
/// Pure function — no IO, no mutation — so it can be unit-tested in
/// isolation and reused from the back-button logic by inverting it.
pub fn next( current: Screen, state: &State ) -> Screen
{
	match current
	{
		Screen::FrontPage              => Screen::SelectLanguage,
		Screen::SelectLanguage         => Screen::Welcome,
		Screen::Welcome                => match state.mode
		{
			WizardMode::Install   => Screen::DiskManagement,
			WizardMode::Configure if state.factory_account => Screen::Account,
			WizardMode::Configure => Screen::Wireless,
		},
		Screen::DiskManagement         => Screen::Account,
		Screen::Account                => match state.mode
		{
			WizardMode::Install   => Screen::InstallProgress,
			WizardMode::Configure => Screen::Wireless,
		},
		Screen::Wireless               => Screen::Navigation,
		Screen::Navigation             => Screen::DataStorage,
		Screen::DataStorage            => match state.storage
		{
			Some( StorageProvider::Proton ) => Screen::DataStorageProton,
			_                               => Screen::Permissions,
		},
		Screen::DataStorageProton      => Screen::Permissions,
		Screen::Permissions            => Screen::SecuritySelector,
		Screen::SecuritySelector       => Screen::InstallFinish,
		Screen::SecurityFingerprintRegister => Screen::SecurityFingerprintDone,
		Screen::SecurityFingerprintDone     => Screen::InstallFinish,
		Screen::InstallProgress        => Screen::InstallFinish,
		Screen::InstallFinish          => match state.mode
		{
			WizardMode::Install   => Screen::Done,
			WizardMode::Configure => Screen::TutorialGestures( 0 ),
		},
		Screen::TutorialGestures( s )  => match s
		{
			0 => Screen::TutorialGestures( 1 ),
			1 => Screen::TutorialGestures( 2 ),
			2 => Screen::TutorialGestures( 3 ),
			_ => Screen::TutorialSmartcast( 0 ),
		},
		Screen::TutorialSmartcast( s ) => match s
		{
			0 => Screen::TutorialSmartcast( 1 ),
			1 => Screen::TutorialSmartcast( 2 ),
			2 => Screen::TutorialSmartcast( 3 ),
			_ => Screen::Done,
		},
		Screen::Done                   => Screen::Done,
	}
}

/// Best-effort previous screen for the chrome's Back button. Only the
/// screens that actually show a Back affordance need a real answer
/// here; the rest map to themselves.
pub fn previous( current: Screen, state: &State ) -> Screen
{
	match current
	{
		Screen::SelectLanguage              => Screen::FrontPage,
		Screen::Welcome                     => Screen::SelectLanguage,
		Screen::DiskManagement              => Screen::Welcome,
		Screen::Account                     => match state.mode
		{
			WizardMode::Install   => Screen::DiskManagement,
			WizardMode::Configure => Screen::Welcome,
		},
		Screen::Wireless                    =>
			if state.mode == WizardMode::Configure && state.factory_account
			{
				Screen::Account
			}
			else
			{
				Screen::Welcome
			},
		Screen::Navigation                  => Screen::Wireless,
		Screen::DataStorage                 => Screen::Navigation,
		Screen::DataStorageProton           => Screen::DataStorage,
		Screen::Permissions                 => match state.storage
		{
			Some( StorageProvider::Proton ) => Screen::DataStorageProton,
			_                               => Screen::DataStorage,
		},
		Screen::SecuritySelector            => Screen::Permissions,
		Screen::SecurityFingerprintRegister => Screen::SecuritySelector,
		Screen::SecurityFingerprintDone     => Screen::SecurityFingerprintRegister,
		Screen::TutorialGestures( s )       => match s
		{
			0 => Screen::InstallFinish,
			n => Screen::TutorialGestures( n - 1 ),
		},
		Screen::TutorialSmartcast( s )      => match s
		{
			0 => Screen::TutorialGestures( 3 ),
			n => Screen::TutorialSmartcast( n - 1 ),
		},
		other => other,
	}
}
