use zeroize::Zeroize;

use crate::field_access;

/// Represents the state for input fields.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Zeroize)]
pub struct InputState {
    mode: InputMode,
    visibility: InputVisibility,
}

impl InputState {
    /// Creates a new [InputState].
    pub const fn new() -> Self {
        Self {
            mode: InputMode::new(),
            visibility: InputVisibility::new(),
        }
    }

    /// Toggles the input visibility.
    pub fn toggle_visibility(&mut self) {
        let vis = match self.visibility {
            InputVisibility::Show => InputVisibility::Hide,
            InputVisibility::Hide => InputVisibility::Show,
        };

        self.set_visibility(vis);
    }
}

field_access! {
    InputState {
        mode: InputMode,
        visibility: InputVisibility,
    }
}

impl Default for InputState {
    fn default() -> Self {
        Self::new()
    }
}

/// Represents the input mode for user input.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Zeroize)]
pub enum InputMode {
    Normal,
    Editing,
}

impl InputMode {
    /// Creates a new [InputMode].
    pub const fn new() -> Self {
        Self::Normal
    }

    /// Gets whether in the editing [InputMode].
    pub const fn is_editing(&self) -> bool {
        matches!(self, Self::Editing)
    }
}

impl Default for InputMode {
    fn default() -> Self {
        Self::new()
    }
}

/// Represents the [InputField](super::InputField) visibility.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Zeroize)]
pub enum InputVisibility {
    /// Show the entry content.
    Show,
    /// Hide the entry content.
    Hide,
}

impl InputVisibility {
    /// Creates a new [InputVisibility].
    pub const fn new() -> Self {
        Self::Show
    }
}

impl Default for InputVisibility {
    fn default() -> Self {
        Self::new()
    }
}
