#![allow(dead_code)]

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum NodeId {
    Element(u32),
    Directive(u32),
}

#[derive(Debug, Clone, PartialEq)]
pub enum Value {
    String(String),
    Int(i64),
    Float(f64),
    Bool(bool),
    Color(String),
    FsPath(String),
    Variable(String),
    Rhei(String),
}

#[derive(Debug, Clone)]
pub enum Directive {
    Version(i64),
    Style(String),
    Global {
        name: String,
        value: Value,
    },
    Singleton {
        name: String,
        prop_span: (u32, u32),
    },
    Component {
        name: String,
        params: Vec<(String, String)>,
        child_span: (u32, u32),
    },
    Let {
        name: String,
        value: Value,
    },
    If {
        condition: Value,
        child_span: (u32, u32),
        else_span: Option<(u32, u32)>,
    },
    Each {
        item: String,
        collection: Value,
        child_span: (u32, u32),
    },
    On {
        event: String,
        args: Vec<(String, Value)>,
        child_span: (u32, u32),
    },
    RheiBlock(String),
}

#[derive(Debug, Default)]
pub struct ModuleSoA {
    pub elem_types: Vec<String>,
    pub elem_prop_spans: Vec<(u32, u32)>,
    pub elem_child_spans: Vec<(u32, u32)>,
    pub elem_content: Vec<Option<Value>>,

    pub prop_keys: Vec<String>,
    pub prop_values: Vec<Value>,

    pub directives: Vec<Directive>,

    pub hierarchy: Vec<NodeId>,
}

impl ModuleSoA {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn push_element(&mut self, typ: String) -> u32 {
        let id = self.elem_types.len() as u32;
        self.elem_types.push(typ);
        self.elem_prop_spans.push((0, 0));
        self.elem_child_spans.push((0, 0));
        self.elem_content.push(None);
        id
    }

    pub fn push_directive(&mut self, dir: Directive) -> u32 {
        let id = self.directives.len() as u32;
        self.directives.push(dir);
        id
    }
}
