darklua_core/nodes/expressions/
table.rsuse crate::{
    nodes::{Expression, Identifier, Token, Trivia},
    process::utils::is_valid_identifier,
};
use super::StringExpression;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableFieldEntry {
    field: Identifier,
    value: Expression,
    token: Option<Token>,
}
impl TableFieldEntry {
    pub fn new<I: Into<Identifier>, E: Into<Expression>>(field: I, value: E) -> Self {
        Self {
            field: field.into(),
            value: value.into(),
            token: None,
        }
    }
    pub fn with_token(mut self, token: Token) -> Self {
        self.token = Some(token);
        self
    }
    #[inline]
    pub fn set_token(&mut self, token: Token) {
        self.token = Some(token);
    }
    #[inline]
    pub fn get_token(&self) -> Option<&Token> {
        self.token.as_ref()
    }
    #[inline]
    pub fn get_field(&self) -> &Identifier {
        &self.field
    }
    #[inline]
    pub fn mutate_field(&mut self) -> &mut Identifier {
        &mut self.field
    }
    #[inline]
    pub fn get_value(&self) -> &Expression {
        &self.value
    }
    #[inline]
    pub fn mutate_value(&mut self) -> &mut Expression {
        &mut self.value
    }
    super::impl_token_fns!(
        target = [field]
        iter = [token]
    );
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableIndexEntryTokens {
    pub opening_bracket: Token,
    pub closing_bracket: Token,
    pub equal: Token,
}
impl TableIndexEntryTokens {
    super::impl_token_fns!(target = [opening_bracket, closing_bracket, equal]);
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableIndexEntry {
    key: Expression,
    value: Expression,
    tokens: Option<Box<TableIndexEntryTokens>>,
}
impl TableIndexEntry {
    pub fn new<T: Into<Expression>, U: Into<Expression>>(key: T, value: U) -> Self {
        Self {
            key: key.into(),
            value: value.into(),
            tokens: None,
        }
    }
    pub fn with_tokens(mut self, tokens: TableIndexEntryTokens) -> Self {
        self.tokens = Some(tokens.into());
        self
    }
    #[inline]
    pub fn set_tokens(&mut self, tokens: TableIndexEntryTokens) {
        self.tokens = Some(tokens.into());
    }
    #[inline]
    pub fn get_tokens(&self) -> Option<&TableIndexEntryTokens> {
        self.tokens.as_ref().map(|tokens| tokens.as_ref())
    }
    #[inline]
    pub fn get_key(&self) -> &Expression {
        &self.key
    }
    #[inline]
    pub fn mutate_key(&mut self) -> &mut Expression {
        &mut self.key
    }
    #[inline]
    pub fn get_value(&self) -> &Expression {
        &self.value
    }
    #[inline]
    pub fn mutate_value(&mut self) -> &mut Expression {
        &mut self.value
    }
    super::impl_token_fns!(iter = [tokens]);
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TableEntry {
    Field(TableFieldEntry),
    Index(TableIndexEntry),
    Value(Expression),
}
impl TableEntry {
    pub fn from_string_key_and_value(key: impl Into<String>, value: impl Into<Expression>) -> Self {
        let key = key.into();
        let value = value.into();
        if is_valid_identifier(&key) {
            Self::Field(TableFieldEntry {
                field: Identifier::new(key),
                value,
                token: None,
            })
        } else {
            Self::Index(TableIndexEntry {
                key: Expression::String(StringExpression::from_value(key)),
                value,
                tokens: None,
            })
        }
    }
    pub fn clear_comments(&mut self) {
        match self {
            TableEntry::Field(entry) => entry.clear_comments(),
            TableEntry::Index(entry) => entry.clear_comments(),
            TableEntry::Value(_) => {}
        }
    }
    pub fn clear_whitespaces(&mut self) {
        match self {
            TableEntry::Field(entry) => entry.clear_whitespaces(),
            TableEntry::Index(entry) => entry.clear_whitespaces(),
            TableEntry::Value(_) => {}
        }
    }
    pub(crate) fn replace_referenced_tokens(&mut self, code: &str) {
        match self {
            TableEntry::Field(entry) => entry.replace_referenced_tokens(code),
            TableEntry::Index(entry) => entry.replace_referenced_tokens(code),
            TableEntry::Value(_) => {}
        }
    }
    pub(crate) fn shift_token_line(&mut self, amount: usize) {
        match self {
            TableEntry::Field(entry) => entry.shift_token_line(amount),
            TableEntry::Index(entry) => entry.shift_token_line(amount),
            TableEntry::Value(_) => {}
        }
    }
    pub(crate) fn filter_comments(&mut self, filter: impl Fn(&Trivia) -> bool) {
        match self {
            TableEntry::Field(entry) => entry.filter_comments(filter),
            TableEntry::Index(entry) => entry.filter_comments(filter),
            TableEntry::Value(_) => {}
        }
    }
}
impl From<TableFieldEntry> for TableEntry {
    fn from(entry: TableFieldEntry) -> Self {
        Self::Field(entry)
    }
}
impl From<TableIndexEntry> for TableEntry {
    fn from(entry: TableIndexEntry) -> Self {
        Self::Index(entry)
    }
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableTokens {
    pub opening_brace: Token,
    pub closing_brace: Token,
    pub separators: Vec<Token>,
}
impl TableTokens {
    super::impl_token_fns!(
        target = [opening_brace, closing_brace]
        iter = [separators]
    );
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableExpression {
    entries: Vec<TableEntry>,
    tokens: Option<TableTokens>,
}
impl TableExpression {
    pub fn new(entries: Vec<TableEntry>) -> Self {
        Self {
            entries,
            tokens: None,
        }
    }
    pub fn with_tokens(mut self, tokens: TableTokens) -> Self {
        self.tokens = Some(tokens);
        self
    }
    #[inline]
    pub fn set_tokens(&mut self, tokens: TableTokens) {
        self.tokens = Some(tokens);
    }
    #[inline]
    pub fn get_tokens(&self) -> Option<&TableTokens> {
        self.tokens.as_ref()
    }
    #[inline]
    pub fn get_entries(&self) -> &Vec<TableEntry> {
        &self.entries
    }
    #[inline]
    pub fn iter_entries(&self) -> impl Iterator<Item = &TableEntry> {
        self.entries.iter()
    }
    #[inline]
    pub fn iter_mut_entries(&mut self) -> impl Iterator<Item = &mut TableEntry> {
        self.entries.iter_mut()
    }
    #[inline]
    pub fn len(&self) -> usize {
        self.entries.len()
    }
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }
    #[inline]
    pub fn mutate_entries(&mut self) -> &mut Vec<TableEntry> {
        &mut self.entries
    }
    pub fn append_entry<T: Into<TableEntry>>(mut self, entry: T) -> Self {
        self.entries.push(entry.into());
        self
    }
    pub fn append_field<S: Into<Identifier>, E: Into<Expression>>(
        mut self,
        key: S,
        value: E,
    ) -> Self {
        self.entries.push(TableFieldEntry::new(key, value).into());
        self
    }
    pub fn append_index<T: Into<Expression>, U: Into<Expression>>(
        mut self,
        key: T,
        value: U,
    ) -> Self {
        self.entries
            .push(TableIndexEntry::new(key.into(), value.into()).into());
        self
    }
    pub fn append_array_value<E: Into<Expression>>(mut self, value: E) -> Self {
        self.entries.push(TableEntry::Value(value.into()));
        self
    }
    super::impl_token_fns!(iter = [tokens, entries]);
}
impl Default for TableExpression {
    fn default() -> Self {
        Self::new(Vec::new())
    }
}