use crossterm::event::{KeyCode, KeyModifiers};
use std::collections::HashMap;
use crate::actions::Action;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyBinding {
    pub code: KeyCode,
    pub modifiers: KeyModifiers,
}

impl KeyBinding {
    pub fn new(code: KeyCode) -> Self {
        Self {
            code,
            modifiers: KeyModifiers::empty(),
        }
    }
}

pub struct KeyMap {
    bindings: HashMap<KeyBinding, Action>,
}

impl KeyMap {
    pub fn new() -> Self {
        Self {
            bindings: HashMap::new(),
        }
    }

    pub fn with_defaults() -> Self {
        let mut map = Self::new();
        map.load_defaults();
        map
    }

    pub fn bind(&mut self, key: KeyBinding, action: Action) {
        self.bindings.insert(key, action);
    }

    pub fn get_action(&self, key: &KeyBinding) -> Option<&Action> {
        self.bindings.get(key)
    }

    pub fn load_defaults(&mut self) {
        // Global
        self.bind(KeyBinding::new(KeyCode::Char('q')), Action::Quit);
        self.bind(KeyBinding::new(KeyCode::Char('?')), Action::ShowHelp);
        self.bind(KeyBinding::new(KeyCode::Char('i')), Action::ShowInfo);
        self.bind(KeyBinding::new(KeyCode::Char('c')), Action::ShowChapters);

        // Screen switching (like cmus)
        self.bind(KeyBinding::new(KeyCode::Char('1')), Action::SwitchToPodcasts);
        self.bind(KeyBinding::new(KeyCode::Char('5')), Action::SwitchToBrowse);

        // Navigation - Arrow keys
        self.bind(KeyBinding::new(KeyCode::Up), Action::MoveUp);
        self.bind(KeyBinding::new(KeyCode::Down), Action::MoveDown);

        // Navigation - Vim keys
        self.bind(KeyBinding::new(KeyCode::Char('k')), Action::MoveUp);
        self.bind(KeyBinding::new(KeyCode::Char('j')), Action::MoveDown);
        self.bind(KeyBinding::new(KeyCode::Char('g')), Action::GoToTop);
        self.bind(KeyBinding::new(KeyCode::Char('G')), Action::GoToBottom);

        // Focus
        self.bind(KeyBinding::new(KeyCode::Tab), Action::SwitchFocus);

        // Feed Management
        self.bind(KeyBinding::new(KeyCode::Char('a')), Action::AddFeed);
        self.bind(KeyBinding::new(KeyCode::Char('d')), Action::DeletePodcast);
        self.bind(KeyBinding::new(KeyCode::Char('r')), Action::RefreshFeed);

        // Episode Management
        self.bind(KeyBinding::new(KeyCode::Char('m')), Action::TogglePlayed);

        // Playback
        self.bind(KeyBinding::new(KeyCode::Char(' ')), Action::PlayPause);
        self.bind(KeyBinding::new(KeyCode::Char('s')), Action::Stop);
        self.bind(KeyBinding::new(KeyCode::Left), Action::SeekBackward);
        self.bind(KeyBinding::new(KeyCode::Right), Action::SeekForward);
        self.bind(KeyBinding::new(KeyCode::Char('h')), Action::SeekBackward);
        self.bind(KeyBinding::new(KeyCode::Char('l')), Action::SeekForward);
        self.bind(KeyBinding::new(KeyCode::Char('[')), Action::SpeedDown);
        self.bind(KeyBinding::new(KeyCode::Char(']')), Action::SpeedUp);
    }
}

impl Default for KeyMap {
    fn default() -> Self {
        Self::with_defaults()
    }
}
