use std::{fs, u8};
use ratatui::crossterm::event::KeyCode;
use serde::Deserialize;
#[derive(Deserialize)]
pub struct KeybindsString {
    pub GoBack:String,
    pub Open:String,
    pub MenuUp:String,
    pub MenuDown:String,
    pub MenuLeft:String,
    pub MenuRight:String,
    pub AddFavourite:String,
}
pub struct Keybinds {
    pub GoBack:KeyCode,
    pub Open:KeyCode,
    pub MenuUp:KeyCode,
    pub MenuDown:KeyCode,
    pub MenuLeft:KeyCode,
    pub MenuRight:KeyCode,
    pub AddFavourite:KeyCode,
}
impl KeybindsString {
    pub fn build() -> Result<Self, String> {
        let f = "keybinds.toml";
        if let Ok(exists)= fs::exists(f) {
            if exists {
                if let Ok(content)= fs::read_to_string(f) {
                    let parsed:KeybindsString = toml::from_str(&content).unwrap();
                    return Ok(parsed);
                }
            }
        }
        return Err(f.to_owned()); 
    }
}
impl Keybinds {
    pub fn build() -> Result<Keybinds, String> {
        let x: Result<Keybinds, String> = match KeybindsString::build() {
            Ok(ks) => Ok(
                Self {
                    GoBack: ks.GoBack.to_key_code()?,
                    Open: ks.Open.to_key_code()?,
                    MenuUp: ks.MenuUp.to_key_code()?,
                    MenuDown: ks.MenuDown.to_key_code()?,
                    MenuLeft: ks.MenuLeft.to_key_code()?,
                    MenuRight: ks.MenuRight.to_key_code()?,
                    AddFavourite: ks.AddFavourite.to_key_code()?,
                }
            ),
            Err(f) => Err(f),
        };
        x
    }
    pub fn buildOrDefault() -> Result<Keybinds, String> {
        let x: Result<Keybinds, String> = match KeybindsString::build() {
            Ok(ks) => Ok(
                Self {
                    GoBack: ks.GoBack.to_key_code().unwrap_or(KeyCode::Esc),
                    Open: ks.Open.to_key_code().unwrap_or(KeyCode::Enter),
                    MenuUp: ks.MenuUp.to_key_code().unwrap_or(KeyCode::Up),
                    MenuDown: ks.MenuDown.to_key_code().unwrap_or(KeyCode::Down),
                    MenuLeft: ks.MenuLeft.to_key_code().unwrap_or(KeyCode::Left),
                    MenuRight: ks.MenuRight.to_key_code().unwrap_or(KeyCode::Right),
                    AddFavourite: ks.AddFavourite.to_key_code().unwrap_or(KeyCode::Char('p')),
                }
            ),
            Err(f) => Err(f),
        };
        x
    }
}
trait StringToKeyCode {
    fn to_key_code(self) -> Result<KeyCode,String>;
}

impl StringToKeyCode for String {
    fn to_key_code(self) -> Result<KeyCode, String> {
       match self.to_uppercase().as_ref() {
            "BACKSPACE"=>Ok(KeyCode::Backspace),
            "ENTER"=>Ok(KeyCode::Enter),
            "LEFT"=>Ok(KeyCode::Left),
            "RIGHT"=>Ok(KeyCode::Right),
            "UP"=>Ok(KeyCode::Up),
            "DOWN"=>Ok(KeyCode::Down),
            "HOME"=>Ok(KeyCode::Home),
            "END"=>Ok(KeyCode::End),
            "PAGEUP"=>Ok(KeyCode::PageUp),
            "PAGEDOWN"=>Ok(KeyCode::PageDown),
            "TAB"=>Ok(KeyCode::Tab),
            "BACKTAB"=>Ok(KeyCode::BackTab),
            "DELETE"=>Ok(KeyCode::Delete),
            "INSERT"=>Ok(KeyCode::Insert),
            "ESC"=>Ok(KeyCode::Esc),
            "CAPSLOCK"=>Ok(KeyCode::CapsLock),
            "SCROLLLOCK"=>Ok(KeyCode::ScrollLock),
            "NUMLOCK"=>Ok(KeyCode::NumLock),
            "PRINTSCREEN"=>Ok(KeyCode::PrintScreen),
            "PAUSE"=>Ok(KeyCode::Pause),
            "MENU"=>Ok(KeyCode::Menu),
            "KEYPADBEGIN"=>Ok(KeyCode::KeypadBegin),
            
            a => {
                let chars: Vec<char> = a.chars().collect();
                return match chars.as_slice() {
                    [c] => Ok(KeyCode::Char(*c)),
                    ['F', d] if d.is_ascii_digit() =>{
                        let dg = d.to_digit(10).unwrap() as u8;
                        Ok(KeyCode::F(dg))
                    },
                    _ => Err(format!("{} is invalid", self))
                };
            }
       }
    }   
}