use clap::{Args, ValueEnum};
use std::str::FromStr;

#[derive(Args)]
pub struct Arguments {
    #[clap(value_enum, value_parser)]
    pub color_depth: ColorType,

    #[clap(value_enum, value_parser, default_value_t=ClutAlignment::None)]
    pub clut_align: ClutAlignment,

    #[clap(long="semi-trans", default_value_t=false)]
    pub semi_transparent: bool,

    #[clap(long="color-trans", default_value_t=false)]
    pub transparent_palette: bool
}

#[derive(Clone)]
pub struct Point {
    pub x: u16,
    pub y: u16,
}

impl Point {
    pub const POINT_VALUE_NAME:&'static str = "{x,y}";    
}

impl std::default::Default for Point {
    fn default() -> Self {
        Point{x: 0, y: 0}
    }
}

impl ToString for Point {
    fn to_string(&self) -> std::string::String {
        "{0,0}".to_owned()
    }
}

impl FromStr for Point {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let values:Vec<&str> = s.split(&['{', ',', '}']).filter_map(|value| if value.is_empty() {None} else {Some(value)}).collect();

        if values.len() != 2 {
            return Err(format!("Two values expected for Point but found {}", values.len()));
        }

        let x = values[0].parse().map_err(|e| format!("Failed converting 'x' for Point: {e}"))?;
        let y = values[1].parse().map_err(|e| format!("Failed converting 'y' for Point: {e}"))?;
        Ok(Point{x, y})
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum ColorType{
    Clut4,
    Clut8,
    Full16,
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum ClutAlignment {
    None,
    Linear,
    Block
}