// SPDX-License-Identifier: GPL-3.0-or-later
use std::{error::Error, path::PathBuf};

use iced::{Settings, window::icon::Icon};

#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum Bool {
    Enable,
    Disable,
}

#[derive(Parser)]
#[command(author, version, about)]
pub struct Cli {
    #[arg(long)]
    pub id: Option<String>,

    #[arg(long)]
    pub text_size: Option<u16>,

    #[arg(long, value_enum, default_value = "enable")]
    pub text_multithreading: Bool,

    #[arg(long, value_enum, default_value = "enable")]
    pub antialiasing: Bool,

    #[arg(short = 's', long, value_name = "WIDTHxHEIGHT", value_parser = parse_size)]
    pub size: Option<(u32, u32)>,

    #[arg(long, value_name = "WIDTHxHEIGHT", value_parser = parse_size)]
    pub min_size: Option<(u32, u32)>,

    #[arg(long, value_name = "WIDTHxHEIGHT", value_parser = parse_size)]
    pub max_size: Option<(u32, u32)>,

    #[arg(long, value_enum, default_value = "enable")]
    pub decorations: Bool,

    #[arg(long, value_enum, default_value = "enable")]
    pub resizable: Bool,

    #[arg(long, value_enum, default_value = "disable")]
    pub transparent: Bool,

    #[arg(long, value_enum, default_value = "enable")]
    pub visible: Bool,

    #[arg(long, value_enum, default_value = "disable")]
    pub always_on_top: Bool,

    #[arg(short, long)]
    pub icon: Option<PathBuf>,
}

fn parse_size(s: &str) -> Result<(u32, u32), Box<dyn Error + Send + Sync>> {
    let (width, height) = s.split_once('x').ok_or("Invalid format, expected WIDTHxHEIGHT")?;
    let width = width.parse()?;
    let height = height.parse()?;
    Ok((width, height))

}

impl Into<bool> for Bool {
    fn into(self) -> bool {
        match self {
            Self::Enable    => true,
            Self::Disable   => false,
        }
    }
}

impl Cli {
    pub fn into_settings<T: Default>(self, flags: T) -> Result<Settings<T>, iced::window::icon::Error> {
        let mut settings = Settings {
            id: self.id,
            text_multithreading: self.text_multithreading.into(),
            antialiasing: self.antialiasing.into(),
            window: iced::window::Settings {
                visible: self.visible.into(),
                resizable: self.resizable.into(),
                decorations: self.decorations.into(),
                transparent: self.transparent.into(),
                always_on_top: self.always_on_top.into(),
                min_size: self.min_size,
                max_size: self.max_size,
                ..Default::default()
            },
            flags,
            ..Default::default()
        };

        if let Some(text_size) = self.text_size {
            settings.default_text_size = text_size;
        }

        if let Some(size) = self.size {
            settings.window.size = size;
        }

        if let Some(icon) = self.icon {
            let icon = Icon::from_file(icon)?;
            settings.window.icon = Some(icon);
        }

        Ok(settings)
    }
}
