A rust port of vgm2mid by Paul Jensen and Valley Bell
use crate::FileType;
use anyhow::{bail, Result};
use clap::{command, Arg, ArgAction};
use std::path::{Path, PathBuf};

pub(crate) fn cli() -> Result<(PathBuf, PathBuf, Option<PathBuf>, FileType, bool, bool)> {
	let matches = command!()
		.arg(
			Arg::new("verbose")
				.action(ArgAction::SetTrue)
				.long("verbose")
				.short('v')
				.help("Prints extra information and any recoverable errors to stderr."),
		)
		.arg(
			Arg::new("strict")
				.action(ArgAction::SetTrue)
				.long("strict")
				.short('s')
				.help("Aborts if any unknown data are encountered during processing."),
		)
		.arg(
			Arg::new("gym")
				.action(ArgAction::SetTrue)
				.long("gym")
				.help("Sets the filetype to gym."),
		)
		.arg(
			Arg::new("vgm")
				.action(ArgAction::SetTrue)
				.conflicts_with("gym")
				.long("vgm")
				.help("Sets the filetype to vgm."),
		)
		.arg(
			Arg::new("zipped")
				.action(ArgAction::SetTrue)
				.requires("vgm")
				.conflicts_with("gym")
				.long("zipped")
				.short('z')
				.help("Extracts gzipped vgms (.vgz)"),
		)
		.arg(
			Arg::new("config")
				.long("config")
				.help("Path to the desired config file."),
		)
		.arg(Arg::new("in").required(true).help(
			"The file to be processed. Filetype is inferred by extension if not set with flags.",
		))
		.arg(
			Arg::new("out")
				.required(true)
				.help("The path to a resulting midi file. Existing files will not be overwritten."),
		)
		.get_matches();

	let in_path = PathBuf::from(matches.get_one::<String>("in").expect("Required"));

	let out_path = PathBuf::from(matches.get_one::<String>("out").expect("Required"));

	let verbose = matches.get_flag("verbose");
	let strict = matches.get_flag("strict");

	let config_path = matches
		.get_one::<PathBuf>("config")
		.map(|pb| pb.to_path_buf());

	let file_type = match (
		matches.get_flag("gym"),
		matches.get_flag("vgm"),
		matches.get_flag("zipped"),
	) {
		(true, false, false) => Ok(FileType::Gym),
		(false, false, false) => determine_file_type(&in_path),
		(false, true, false) => Ok(FileType::Vgm),
		(false, true, true) => Ok(FileType::Vgz),
		_ => bail!("Invalid flag combination"),
	}?;

	Ok((in_path, out_path, config_path, file_type, verbose, strict))
}

fn determine_file_type(in_path: &Path) -> Result<FileType> {
	println!("File type flag not set. Attempting to determine file type.");
	match in_path.extension().and_then(|osstr| osstr.to_str()) {
		Some("gym") => {
			println!("Determined file type to be gym from {}", in_path.display());
			Ok(FileType::Gym)
		},
		Some("vgm") => {
			println!("Determined file type to be vgm from {}", in_path.display());
			Ok(FileType::Vgm)
		},
		Some("vgz") => {
			println!("Determined file type to be vgz from {}", in_path.display());
			Ok(FileType::Vgz)
		},
		_ => bail!("Unrecognized file extension from {}", in_path.display()),
	}
}