use dioxus::prelude::*;

#[derive(Default, PartialEq, Props, Clone)]
pub struct UserPrefs {
    theme: ThemePref,
    font: FontPref,
}

#[derive(Default, PartialEq, Clone)]
pub enum ThemePref {
    Light,
    Dark,
    #[default]
    Auto,
}

#[derive(Default, PartialEq, Clone)]
pub enum FontPref {
    #[default]
    NerdFont,
    OpenDyslexic,
}

pub enum ThemedComponent {
    Page,
    Card,
    Button,
}

impl UserPrefs {
    // TailwindCSS has a difficult time determining which classes we'll need for our site,
    // the easiest way to fix this is to simply list all of them our in commented out class
    // attributes, so all of these we *will* use, and TailwindCSS will know to compile them.
    // class: "bg-alice-werefox-grey-light dark:bg-alice-werefox-grey"
    // class: "bg-alice-werefox-grey"
    // class: "bg-alice-werefox-grey-lightest ring-alice-werefox-red-dark text-alice-werefox-grey-dark"
    // class: "dark:bg-alice-werefox-grey-dark dark:ring-alice-werefox-red dark:text-alice-werefox-grey-light"
    // class: "bg-alice-werefox-grey-dark ring-alice-werefox-red text-alice-werefox-grey-light"
    // class: "bg-alice-werefox-grey-lightest ring-alice-werefox-red-dark text-alice-werefox-grey-dark"
    // class: "hover:text-alice-werefox-blue-dark"
    // class: "hover:ring-alice-werefox-blue dark:bg-alice-werefox-grey-dark dark:ring-alice-werefox-red"
    // class: "bg-alice-werefox-grey-dark ring-alice-werefox-red"
    // class: "dark:text-alice-werefox-grey-light dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue"
    // class: "text-alice-werefox-grey-light hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue"

    const PAGE_CLASSES: &'static str = "bg-alice-werefox-grey-light dark:bg-alice-werefox-grey";
    const CARD_CLASSES: &'static str = "bg-alice-werefox-grey-lightest ring-alice-werefox-red-dark text-alice-werefox-grey-dark dark:bg-alice-werefox-grey-dark dark:ring-alice-werefox-red dark:text-alice-werefox-grey-light";
    const BUTTON_CLASSES: &'static str = "bg-alice-werefox-grey-lightest ring-alice-werefox-red-dark text-alice-werefox-grey-dark hover:text-alice-werefox-blue-dark hover:ring-alice-werefox-blue dark:bg-alice-werefox-grey-dark dark:ring-alice-werefox-red dark:text-alice-werefox-grey-light dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue";

    pub fn new(theme: ThemePref, font: FontPref) -> UserPrefs {
        UserPrefs { theme, font }
    }

    // I'm really about to write a ceil() function because I refuse to force devs to use Nightly
    fn ceil(n: usize) -> usize {
        if n.rem_euclid(2) == 0 {
            n / 2
        } else {
            n - 1 / 2
        }
    }

    pub fn get_pref_classes(&self, component: ThemedComponent) -> (String, String) {
        let theme = self.get_theme_classes(component).clone();
        let font = self.get_font_class().clone();
        (theme, font)
    }

    pub fn get_theme_classes(&self, component: ThemedComponent) -> String {
        match &self.theme {
            ThemePref::Light => match component {
                ThemedComponent::Page => Self::PAGE_CLASSES
                    .split_at(Self::ceil(Self::PAGE_CLASSES.len() / 2))
                    .0
                    .to_string(),
                ThemedComponent::Card => Self::CARD_CLASSES
                    .split_at(Self::ceil(Self::CARD_CLASSES.len() / 2))
                    .0
                    .to_string(),
                ThemedComponent::Button => Self::BUTTON_CLASSES
                    .split_at(Self::ceil(Self::BUTTON_CLASSES.len() / 2))
                    .0
                    .to_string(),
            },
            ThemePref::Dark => match component {
                ThemedComponent::Page => {
                    let remove_dark_tags = Self::PAGE_CLASSES.split("dark:").collect::<String>();
                    let split_whitespace = remove_dark_tags.as_str().split(" ");
                    let split_whitespace_length = split_whitespace.clone().count();
                    split_whitespace
                        .skip(Self::ceil(split_whitespace_length / 2))
                        .map(|e| format!("{e} "))
                        .collect::<String>()
                }
                ThemedComponent::Card => {
                    let remove_dark_tags = Self::CARD_CLASSES.split("dark:").collect::<String>();
                    let split_whitespace = remove_dark_tags.as_str().split(" ");
                    let split_whitespace_length = split_whitespace.clone().count();
                    split_whitespace
                        .skip(Self::ceil(split_whitespace_length / 2))
                        .map(|e| format!("{e} "))
                        .collect::<String>()
                }
                ThemedComponent::Button => {
                    let remove_dark_tags = Self::BUTTON_CLASSES.split("dark:").collect::<String>();
                    let split_whitespace = remove_dark_tags.as_str().split(" ");
                    let split_whitespace_length = split_whitespace.clone().count();
                    split_whitespace
                        .skip(Self::ceil(split_whitespace_length / 2))
                        .map(|e| format!("{e} "))
                        .collect::<String>()
                }
            },
            ThemePref::Auto => match component {
                ThemedComponent::Page => Self::PAGE_CLASSES.to_string(),
                ThemedComponent::Card => Self::CARD_CLASSES.to_string(),
                ThemedComponent::Button => Self::BUTTON_CLASSES.to_string(),
            },
        }
    }

    pub fn get_font_class(&self) -> String {
        match &self.font {
            FontPref::OpenDyslexic => "font-open".to_string(),
            FontPref::NerdFont => "font-nerd".to_string(),
        }
    }

    pub fn set_prefs(mut self, prefs: UserPrefs) {
        self.theme = prefs.theme;
        self.font = prefs.font;
    }

    pub fn set_theme(mut self, theme: ThemePref) {
        self.theme = theme;
    }

    pub fn set_font(mut self, font: FontPref) {
        self.font = font;
    }

    pub fn get_prefs(self) -> (ThemePref, FontPref) {
        let prefs = self.clone();
        (prefs.theme, prefs.font)
    }

    pub fn get_theme(self) -> ThemePref {
        let prefs = self.clone();
        prefs.theme.clone()
    }

    pub fn get_font(self) -> FontPref {
        let prefs = self.clone();
        prefs.font.clone()
    }
}
