use crate::canvas::actions::CanvasAction;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum CanvasKeyAction {
    MoveLeft,
    MoveRight,
    MoveUp,
    MoveDown,
    NextField,
    PrevField,
    MoveLineStart,
    MoveLineEnd,
    MoveHalfPageUp,
    MoveHalfPageDown,
    MoveFirstLine,
    MoveLastLine,
    MoveWordNext,
    MoveWordPrev,
    MoveWordEnd,
    MoveWordEndPrev,
    MoveBigWordNext,
    MoveBigWordPrev,
    MoveBigWordEnd,
    MoveBigWordEndPrev,
    DeleteCharBackward,
    DeleteCharForward,
    Undo,
    Redo,
    OpenLineBelow,
    OpenLineAbove,
    EnterEditModeLineStart,
    EnterEditModeLineEnd,
    DeleteLine,
    DeleteToLineEnd,
    ChangeLine,
    ChangeToLineEnd,
    OperatorDelete,
    OperatorChange,
    OperatorYank,
    JoinLineBelow,
    YankLine,
    PasteAfter,
    PasteBefore,
    OpenSuggestions,
    ApplySuggestion,
    EnterDecider,
    SuggestionDown,
    SuggestionUp,
    EnterEditModeBefore,
    EnterEditModeAfter,
    Exit,
    ExitEditMode,
    EnterHighlightMode,
    EnterHighlightModeLinewise,
    ExitHighlightMode,
    DeleteSelection,
    DeleteSelectionNoYank,
    ChangeSelection,
    ChangeSelectionNoYank,
    YankSelection,
    CollapseSelection,
    ExtendLineBelow,
    ExtendToLineBounds,
    SearchNext,
    SearchPrev,
    SelectAll,
    FlipSelections,
    SwitchCase,
    SwitchToLowercase,
    SwitchToUppercase,
    TrimSelections,
    GotoFirstNonWhitespace,
    MovePageUp,
    MovePageDown,
    SearchSelection,
    EnsureSelectionForward,
    MatchBrackets,
    IndentSelection,
    UnindentSelection,
    IncrementNumber,
    DecrementNumber,
    FindNextChar,
    FindPrevChar,
    TillNextChar,
    TillPrevChar,
    ReplaceChar,
    RepeatLastFind,
    RepeatLastFindReverse,
    SurroundAdd,
    SurroundDelete,
    SurroundReplace,
    DeleteWordBackward,
    DeleteToLineStart,
    DeleteWordForward,
    ClearSearch,
    Unknown(String),
}

impl CanvasKeyAction {
    pub fn from_name(name: &str) -> Self {
        match name {
            "move_left" => Self::MoveLeft,
            "move_right" => Self::MoveRight,
            "move_up" => Self::MoveUp,
            "move_down" => Self::MoveDown,
            "next_field" => Self::NextField,
            "prev_field" => Self::PrevField,
            "move_line_start" => Self::MoveLineStart,
            "move_line_end" => Self::MoveLineEnd,
            "move_half_page_up" => Self::MoveHalfPageUp,
            "move_half_page_down" => Self::MoveHalfPageDown,
            "move_first_line" => Self::MoveFirstLine,
            "move_last_line" => Self::MoveLastLine,
            "move_word_next" => Self::MoveWordNext,
            "move_word_prev" => Self::MoveWordPrev,
            "move_word_end" => Self::MoveWordEnd,
            "move_word_end_prev" => Self::MoveWordEndPrev,
            "move_big_word_next" => Self::MoveBigWordNext,
            "move_big_word_prev" => Self::MoveBigWordPrev,
            "move_big_word_end" => Self::MoveBigWordEnd,
            "move_big_word_end_prev" => Self::MoveBigWordEndPrev,
            "delete_char_backward" => Self::DeleteCharBackward,
            "delete_char_forward" => Self::DeleteCharForward,
            "undo" => Self::Undo,
            "redo" => Self::Redo,
            "open_line_below" => Self::OpenLineBelow,
            "open_line_above" => Self::OpenLineAbove,
            "enter_edit_mode_line_start" => Self::EnterEditModeLineStart,
            "enter_edit_mode_line_end" => Self::EnterEditModeLineEnd,
            "delete_line" => Self::DeleteLine,
            "delete_to_line_end" => Self::DeleteToLineEnd,
            "change_line" => Self::ChangeLine,
            "change_to_line_end" => Self::ChangeToLineEnd,
            "operator_delete" => Self::OperatorDelete,
            "operator_change" => Self::OperatorChange,
            "operator_yank" => Self::OperatorYank,
            "join_line_below" => Self::JoinLineBelow,
            "yank_line" => Self::YankLine,
            "paste_after" => Self::PasteAfter,
            "paste_before" => Self::PasteBefore,
            "open_suggestions" => Self::OpenSuggestions,
            "apply_suggestion" => Self::ApplySuggestion,
            "enter_decider" => Self::EnterDecider,
            "suggestion_down" => Self::SuggestionDown,
            "suggestion_up" => Self::SuggestionUp,
            "enter_edit_mode_before" => Self::EnterEditModeBefore,
            "enter_edit_mode_after" => Self::EnterEditModeAfter,
            "exit" => Self::Exit,
            "exit_edit_mode" => Self::ExitEditMode,
            "enter_highlight_mode" => Self::EnterHighlightMode,
            "enter_highlight_mode_linewise" => Self::EnterHighlightModeLinewise,
            "exit_highlight_mode" => Self::ExitHighlightMode,
            "delete_selection" => Self::DeleteSelection,
            "delete_selection_noyank" => Self::DeleteSelectionNoYank,
            "change_selection" => Self::ChangeSelection,
            "change_selection_noyank" => Self::ChangeSelectionNoYank,
            "yank_selection" => Self::YankSelection,
            "collapse_selection" => Self::CollapseSelection,
            "extend_line_below" => Self::ExtendLineBelow,
            "extend_to_line_bounds" => Self::ExtendToLineBounds,
            "search_next" => Self::SearchNext,
            "search_prev" => Self::SearchPrev,
            "select_all" => Self::SelectAll,
            "flip_selections" => Self::FlipSelections,
            "switch_case" => Self::SwitchCase,
            "switch_to_lowercase" => Self::SwitchToLowercase,
            "switch_to_uppercase" => Self::SwitchToUppercase,
            "trim_selections" => Self::TrimSelections,
            "goto_first_nonwhitespace" => Self::GotoFirstNonWhitespace,
            "move_page_up" => Self::MovePageUp,
            "move_page_down" => Self::MovePageDown,
            "search_selection" => Self::SearchSelection,
            "ensure_selection_forward" => Self::EnsureSelectionForward,
            "match_brackets" => Self::MatchBrackets,
            "indent_selection" => Self::IndentSelection,
            "unindent_selection" => Self::UnindentSelection,
            "increment_number" => Self::IncrementNumber,
            "decrement_number" => Self::DecrementNumber,
            "find_next_char" => Self::FindNextChar,
            "find_prev_char" => Self::FindPrevChar,
            "till_next_char" => Self::TillNextChar,
            "till_prev_char" => Self::TillPrevChar,
            "replace_char" => Self::ReplaceChar,
            "repeat_last_find" => Self::RepeatLastFind,
            "repeat_last_find_reverse" => Self::RepeatLastFindReverse,
            "surround_add" => Self::SurroundAdd,
            "surround_delete" => Self::SurroundDelete,
            "surround_replace" => Self::SurroundReplace,
            "delete_word_backward" => Self::DeleteWordBackward,
            "delete_to_line_start" => Self::DeleteToLineStart,
            "delete_word_forward" => Self::DeleteWordForward,
            "clear_search" => Self::ClearSearch,
            other => Self::Unknown(other.to_string()),
        }
    }

    pub fn as_str(&self) -> &str {
        match self {
            Self::MoveLeft => "move_left",
            Self::MoveRight => "move_right",
            Self::MoveUp => "move_up",
            Self::MoveDown => "move_down",
            Self::NextField => "next_field",
            Self::PrevField => "prev_field",
            Self::MoveLineStart => "move_line_start",
            Self::MoveLineEnd => "move_line_end",
            Self::MoveHalfPageUp => "move_half_page_up",
            Self::MoveHalfPageDown => "move_half_page_down",
            Self::MoveFirstLine => "move_first_line",
            Self::MoveLastLine => "move_last_line",
            Self::MoveWordNext => "move_word_next",
            Self::MoveWordPrev => "move_word_prev",
            Self::MoveWordEnd => "move_word_end",
            Self::MoveWordEndPrev => "move_word_end_prev",
            Self::MoveBigWordNext => "move_big_word_next",
            Self::MoveBigWordPrev => "move_big_word_prev",
            Self::MoveBigWordEnd => "move_big_word_end",
            Self::MoveBigWordEndPrev => "move_big_word_end_prev",
            Self::DeleteCharBackward => "delete_char_backward",
            Self::DeleteCharForward => "delete_char_forward",
            Self::Undo => "undo",
            Self::Redo => "redo",
            Self::OpenLineBelow => "open_line_below",
            Self::OpenLineAbove => "open_line_above",
            Self::EnterEditModeLineStart => "enter_edit_mode_line_start",
            Self::EnterEditModeLineEnd => "enter_edit_mode_line_end",
            Self::DeleteLine => "delete_line",
            Self::DeleteToLineEnd => "delete_to_line_end",
            Self::ChangeLine => "change_line",
            Self::ChangeToLineEnd => "change_to_line_end",
            Self::OperatorDelete => "operator_delete",
            Self::OperatorChange => "operator_change",
            Self::OperatorYank => "operator_yank",
            Self::JoinLineBelow => "join_line_below",
            Self::YankLine => "yank_line",
            Self::PasteAfter => "paste_after",
            Self::PasteBefore => "paste_before",
            Self::OpenSuggestions => "open_suggestions",
            Self::ApplySuggestion => "apply_suggestion",
            Self::EnterDecider => "enter_decider",
            Self::SuggestionDown => "suggestion_down",
            Self::SuggestionUp => "suggestion_up",
            Self::EnterEditModeBefore => "enter_edit_mode_before",
            Self::EnterEditModeAfter => "enter_edit_mode_after",
            Self::Exit => "exit",
            Self::ExitEditMode => "exit_edit_mode",
            Self::EnterHighlightMode => "enter_highlight_mode",
            Self::EnterHighlightModeLinewise => "enter_highlight_mode_linewise",
            Self::ExitHighlightMode => "exit_highlight_mode",
            Self::DeleteSelection => "delete_selection",
            Self::DeleteSelectionNoYank => "delete_selection_noyank",
            Self::ChangeSelection => "change_selection",
            Self::ChangeSelectionNoYank => "change_selection_noyank",
            Self::YankSelection => "yank_selection",
            Self::CollapseSelection => "collapse_selection",
            Self::SearchNext => "search_next",
            Self::SearchPrev => "search_prev",
            Self::SelectAll => "select_all",
            Self::FlipSelections => "flip_selections",
            Self::SwitchCase => "switch_case",
            Self::SwitchToLowercase => "switch_to_lowercase",
            Self::SwitchToUppercase => "switch_to_uppercase",
            Self::TrimSelections => "trim_selections",
            Self::GotoFirstNonWhitespace => "goto_first_nonwhitespace",
            Self::MovePageUp => "move_page_up",
            Self::MovePageDown => "move_page_down",
            Self::SearchSelection => "search_selection",
            Self::EnsureSelectionForward => "ensure_selection_forward",
            Self::MatchBrackets => "match_brackets",
            Self::IndentSelection => "indent_selection",
            Self::UnindentSelection => "unindent_selection",
            Self::IncrementNumber => "increment_number",
            Self::DecrementNumber => "decrement_number",
            Self::FindNextChar => "find_next_char",
            Self::FindPrevChar => "find_prev_char",
            Self::TillNextChar => "till_next_char",
            Self::TillPrevChar => "till_prev_char",
            Self::ReplaceChar => "replace_char",
            Self::RepeatLastFind => "repeat_last_find",
            Self::RepeatLastFindReverse => "repeat_last_find_reverse",
            Self::SurroundAdd => "surround_add",
            Self::SurroundDelete => "surround_delete",
            Self::SurroundReplace => "surround_replace",
            Self::DeleteWordBackward => "delete_word_backward",
            Self::DeleteToLineStart => "delete_to_line_start",
            Self::DeleteWordForward => "delete_word_forward",
            Self::ClearSearch => "clear_search",
            Self::ExtendLineBelow => "extend_line_below",
            Self::ExtendToLineBounds => "extend_to_line_bounds",
            Self::Unknown(other) => other.as_str(),
        }
    }

    pub fn to_canvas_action(&self) -> Option<CanvasAction> {
        Some(match self {
            Self::MoveLeft => CanvasAction::MoveLeft,
            Self::MoveRight => CanvasAction::MoveRight,
            Self::MoveUp => CanvasAction::MoveUp,
            Self::MoveDown => CanvasAction::MoveDown,
            Self::MoveWordNext => CanvasAction::MoveWordNext,
            Self::MoveWordPrev => CanvasAction::MoveWordPrev,
            Self::MoveWordEnd => CanvasAction::MoveWordEnd,
            Self::MoveWordEndPrev => CanvasAction::MoveWordEndPrev,
            Self::MoveBigWordNext => CanvasAction::MoveBigWordNext,
            Self::MoveBigWordPrev => CanvasAction::MoveBigWordPrev,
            Self::MoveBigWordEnd => CanvasAction::MoveBigWordEnd,
            Self::MoveBigWordEndPrev => CanvasAction::MoveBigWordEndPrev,
            Self::MoveLineStart => CanvasAction::MoveLineStart,
            Self::MoveLineEnd => CanvasAction::MoveLineEnd,
            Self::MoveHalfPageUp | Self::MoveHalfPageDown => return None,
            Self::NextField => CanvasAction::NextField,
            Self::PrevField => CanvasAction::PrevField,
            Self::MoveFirstLine => CanvasAction::MoveFirstLine,
            Self::MoveLastLine => CanvasAction::MoveLastLine,
            Self::DeleteCharBackward => CanvasAction::DeleteBackward,
            Self::DeleteCharForward => CanvasAction::DeleteForward,
            Self::Undo => CanvasAction::Undo,
            Self::Redo => CanvasAction::Redo,
            Self::OpenSuggestions => CanvasAction::TriggerSuggestions,
            Self::SuggestionUp => CanvasAction::SuggestionUp,
            Self::SuggestionDown => CanvasAction::SuggestionDown,
            Self::ApplySuggestion => CanvasAction::SelectSuggestion,
            Self::EnterEditModeBefore => CanvasAction::EnterEditMode,
            Self::EnterEditModeAfter => CanvasAction::EnterEditModeAfter,
            Self::ExitEditMode => CanvasAction::ExitEditMode,
            Self::EnterHighlightMode => CanvasAction::EnterHighlightMode,
            Self::EnterHighlightModeLinewise => CanvasAction::EnterHighlightModeLinewise,
            Self::ExitHighlightMode => CanvasAction::ExitHighlightMode,
            Self::OpenLineBelow => CanvasAction::OpenLineBelow,
            Self::OpenLineAbove => CanvasAction::OpenLineAbove,
            Self::EnterEditModeLineStart
            | Self::EnterEditModeLineEnd
            | Self::DeleteLine
            | Self::DeleteToLineEnd
            | Self::ChangeLine
            | Self::ChangeToLineEnd
            | Self::OperatorDelete
            | Self::OperatorChange
            | Self::OperatorYank
            | Self::JoinLineBelow
            | Self::YankLine
            |             Self::PasteAfter
            | Self::PasteBefore
            | Self::DeleteSelection
            | Self::DeleteSelectionNoYank
            | Self::ChangeSelection
            | Self::ChangeSelectionNoYank
            | Self::YankSelection
            | Self::CollapseSelection
            | Self::ExtendLineBelow
            | Self::ExtendToLineBounds
            | Self::SearchNext
            | Self::SearchPrev
            | Self::SelectAll
            | Self::FlipSelections
            | Self::SwitchCase
            | Self::SwitchToLowercase
            | Self::SwitchToUppercase
            | Self::TrimSelections
            | Self::GotoFirstNonWhitespace
            | Self::MovePageUp
            | Self::MovePageDown
            | Self::SearchSelection
            | Self::EnsureSelectionForward
            | Self::MatchBrackets
            | Self::IndentSelection
            | Self::UnindentSelection
            | Self::IncrementNumber
            | Self::DecrementNumber
            | Self::FindNextChar
            | Self::FindPrevChar
            | Self::TillNextChar
            | Self::TillPrevChar
            | Self::ReplaceChar
            | Self::RepeatLastFind
            | Self::RepeatLastFindReverse
            | Self::SurroundAdd
            | Self::SurroundDelete
            | Self::SurroundReplace
            | Self::DeleteWordBackward
            | Self::DeleteToLineStart
            | Self::DeleteWordForward
            | Self::ClearSearch => return None,
            Self::EnterDecider | Self::Exit | Self::Unknown(_) => return None,
        })
    }
}
