// Tiny argv parser for the installer.
//
// We avoid pulling in a full argument-parsing crate because the
// surface is two flags (`--windowsize` and `--help`) and the binary is
// a self-contained installer that should ship without extra deps.

const USAGE: &str = "\
Usage: eydos-installer [OPTIONS]
       eydos-installer daemon
       eydos-installer firstboot

Subcommands:
  daemon              Run the privileged backend (root). Started by
                      eydos-installer-daemon.service; executes installs
                      and marker swaps on behalf of the wizard.
  firstboot           Run the first-boot fixups (root): direct-flash
                      detection, the staged account rename and the
                      re-encryption follow-up. Started as ExecStartPre
                      of the daemon unit, before any session exists.

Options:
  --windowsize WxH    Open a centred window of the given pixel size
                      (e.g. --windowsize 1600x900). Defaults to fullscreen.
  --test              Walk the full wizard without touching the machine:
                      disk operations, wifi connects and the install
                      itself are simulated.
  --install           Force the install scenario (target disk + system
                      copy). Default when the configure-pending marker
                      is absent.
  --configure         Force the first-boot configure scenario (wireless,
                      navigation, storage, permissions, security,
                      tutorials). Default when the marker written by a
                      finished install is present.
  -h, --help          Print this help and exit.
";

use crate::state::WizardMode;

pub struct Cli
{
	pub window_size: Option<( u32, u32 )>,
	pub test:        bool,
	/// `None` means auto-detect from the configure-pending marker.
	pub mode:        Option<WizardMode>,
	/// `eydos-installer daemon`: run the privileged backend, no GUI.
	pub daemon:      bool,
	/// `eydos-installer firstboot`: run the first-boot fixups, no GUI.
	pub firstboot:   bool,
}

pub fn parse() -> Cli
{
	let mut window_size: Option<( u32, u32 )> = None;
	let mut test = false;
	let mut mode: Option<WizardMode> = None;
	let mut daemon = false;
	let mut firstboot = false;
	let mut args = std::env::args().skip( 1 );

	while let Some( arg ) = args.next()
	{
		match arg.as_str()
		{
			"-h" | "--help" =>
			{
				print!( "{}", USAGE );
				std::process::exit( 0 );
			}
			"daemon"      => daemon = true,
			"firstboot"   => firstboot = true,
			"--test"      => test = true,
			"--install"   => mode = Some( WizardMode::Install ),
			"--configure" => mode = Some( WizardMode::Configure ),
			"--windowsize" =>
			{
				let value = args.next().unwrap_or_else( ||
				{
					eprintln!( "error: --windowsize expects a value like 1600x900" );
					std::process::exit( 2 );
				} );
				window_size = Some( parse_size( &value ) );
			}
			other if other.starts_with( "--windowsize=" ) =>
			{
				let value = &other[ "--windowsize=".len().. ];
				window_size = Some( parse_size( value ) );
			}
			other =>
			{
				eprintln!( "error: unknown argument {:?}", other );
				eprint!( "{}", USAGE );
				std::process::exit( 2 );
			}
		}
	}

	Cli { window_size, test, mode, daemon, firstboot }
}

fn parse_size( s: &str ) -> ( u32, u32 )
{
	let parts: Vec<&str> = s.split( |c| c == 'x' || c == 'X' || c == '*' ).collect();
	if parts.len() != 2
	{
		eprintln!( "error: --windowsize must be WxH (got {:?})", s );
		std::process::exit( 2 );
	}
	let w: u32 = parts[ 0 ].trim().parse().unwrap_or_else( |_|
	{
		eprintln!( "error: --windowsize: bad width {:?}", parts[ 0 ] );
		std::process::exit( 2 );
	} );
	let h: u32 = parts[ 1 ].trim().parse().unwrap_or_else( |_|
	{
		eprintln!( "error: --windowsize: bad height {:?}", parts[ 1 ] );
		std::process::exit( 2 );
	} );
	if w == 0 || h == 0
	{
		eprintln!( "error: --windowsize must be positive, got {}x{}", w, h );
		std::process::exit( 2 );
	}
	( w, h )
}
