//! Motion module for cursor movement types
//!
//! This module defines the `Motion` enum representing all possible cursor movements.
//! Motion calculations are implemented in `buffer::cursor::calculate_motion`.

/// All possible cursor motions
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Motion {
    // Character motions
    Left,
    Right,
    Up,
    Down,

    // Line motions
    LineStart,
    LineEnd,

    // Word motions
    WordForward,
    WordBackward,
    WordEnd,

    // Document motions
    DocumentStart,
    DocumentEnd,

    // Jump motions (for plugins like range-finder, LSP goto definition, etc.)
    /// Jump to specific line and column
    JumpTo {
        line: u32,
        column: u32,
    },

    // Bracket matching
    /// Jump to matching bracket (%, vim-style)
    MatchingBracket,
}

impl Motion {
    /// Check if this motion operates on whole lines (linewise)
    ///
    /// Linewise motions delete/yank entire lines rather than character ranges.
    /// Used by operators like `dj` (delete current + next line) vs `dw` (delete word).
    #[must_use]
    pub const fn is_linewise(&self) -> bool {
        matches!(self, Self::Up | Self::Down | Self::DocumentStart | Self::DocumentEnd)
    }

    /// Check if this motion is inclusive
    ///
    /// Inclusive motions include the character at the target position in
    /// operations. In vim:
    /// - `$` (`LineEnd`) and `e` (`WordEnd`) are inclusive
    /// - `w` (`WordForward`) and `b` (`WordBackward`) are exclusive
    /// - `%` (`MatchingBracket`) is inclusive
    #[must_use]
    pub const fn is_inclusive(&self) -> bool {
        matches!(self, Self::LineEnd | Self::WordEnd | Self::MatchingBracket)
    }

    /// Parse a key string into a motion
    #[must_use]
    pub fn from_key(key: &str) -> Option<Self> {
        match key {
            "h" => Some(Self::Left),
            "l" => Some(Self::Right),
            "j" => Some(Self::Down),
            "k" => Some(Self::Up),
            "w" => Some(Self::WordForward),
            "b" => Some(Self::WordBackward),
            "e" => Some(Self::WordEnd),
            "0" => Some(Self::LineStart),
            "$" => Some(Self::LineEnd),
            "G" => Some(Self::DocumentEnd),
            "gg" => Some(Self::DocumentStart),
            "%" => Some(Self::MatchingBracket),
            _ => None,
        }
    }
}
