//! Parameter parsing and management for HeroScript.
//!
//! This module provides the `Params` type for parsing and accessing
//! key-value parameters, positional arguments, and comments.

mod export;
mod getters;
mod lists;
mod parser;
mod setters;

pub use export::ExportArgs;
pub use parser::parse;

use super::errors::ParamsError;
use serde::{Deserialize, Serialize};

/// A single key-value parameter with optional comment.
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct Param {
    /// The parameter key (normalized to lowercase).
    pub key: String,
    /// The parameter value.
    pub value: String,
    /// Optional comment associated with this parameter.
    pub comment: String,
}

impl Param {
    /// Create a new parameter with the given key and value.
    pub fn new(key: &str, value: &str) -> Self {
        Self {
            key: key.to_lowercase(),
            value: value.to_string(),
            comment: String::new(),
        }
    }

    /// Create a new parameter with a comment.
    pub fn with_comment(key: &str, value: &str, comment: &str) -> Self {
        Self {
            key: key.to_lowercase(),
            value: value.to_string(),
            comment: comment.to_string(),
        }
    }
}

/// Collection of parameters, positional arguments, and comments.
///
/// # Example
///
/// ```
/// use herosal_heroscript::params::{Params, parse};
///
/// let params = parse("name:'John Doe' age:30 debug").unwrap();
/// assert_eq!(params.get("name").unwrap(), "John Doe");
/// assert_eq!(params.get_int("age").unwrap(), 30);
/// assert!(params.exists_arg("debug"));
/// ```
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct Params {
    /// Key-value parameters.
    pub params: Vec<Param>,
    /// Positional arguments (values without keys).
    pub args: Vec<String>,
    /// Top-level comments.
    pub comments: Vec<String>,
}

impl Params {
    /// Create a new empty Params instance.
    pub fn new() -> Self {
        Self::default()
    }

    /// Parse a parameter string into a Params instance.
    ///
    /// This is a convenience method that calls `parse()`.
    pub fn parse(text: &str) -> Result<Self, ParamsError> {
        parse(text)
    }

    /// Find a parameter by key (case-insensitive).
    fn find_param(&self, key: &str) -> Option<&Param> {
        let key_lower = key.to_lowercase();
        self.params.iter().find(|p| p.key == key_lower)
    }

    /// Find a mutable parameter by key (case-insensitive).
    fn find_param_mut(&mut self, key: &str) -> Option<&mut Param> {
        let key_lower = key.to_lowercase();
        self.params.iter_mut().find(|p| p.key == key_lower)
    }

    /// Find the index of a parameter by key.
    fn find_param_index(&self, key: &str) -> Option<usize> {
        let key_lower = key.to_lowercase();
        self.params.iter().position(|p| p.key == key_lower)
    }
}
