use std::{collections::HashMap, rc::Rc};

use crate::node::NodeEnum;

pub type EnvironmentInternalSymbolKey = u16;
// pub type Environment = HashMap<EnvironmentInternalSymbolKey, Rc<NodeEnum>>;

pub struct Environment {
    map: HashMap<EnvironmentInternalSymbolKey, Rc<NodeEnum>>,

    symbol_to_id: HashMap<String, EnvironmentInternalSymbolKey>,
    id_to_symbol: HashMap<EnvironmentInternalSymbolKey, String>,
    unique_keys: EnvironmentInternalSymbolKey
}

impl Environment {
    pub fn new() -> Self {
        Self {
            map: HashMap::new(),

            symbol_to_id: HashMap::new(),
            id_to_symbol: HashMap::new(),
            unique_keys: 0
        }
    }

    pub fn get(&self, key: &EnvironmentInternalSymbolKey) -> Option<&Rc<NodeEnum>> {
        self.map.get(key)
    }

    pub fn insert(&mut self, key: EnvironmentInternalSymbolKey, value: Rc<NodeEnum>) {
        self.map.insert(key, value);
    }

    pub fn str_to_id(&self, value: &String) -> Option<&EnvironmentInternalSymbolKey> {
        self.symbol_to_id.get(value)
    }
    pub fn id_to_str(&self, value: &EnvironmentInternalSymbolKey) -> Option<&String> {
        self.id_to_symbol.get(value)
    }
    pub fn insert_str_to_id(&mut self, key: String, value: EnvironmentInternalSymbolKey) {
        self.symbol_to_id.insert(key.clone(), value);
        self.id_to_symbol.insert(value, key);
    }
    pub fn insert_id_to_str(&mut self, key: EnvironmentInternalSymbolKey, value: String) {
        self.id_to_symbol.insert(key, value.clone());
        self.symbol_to_id.insert(value, key);
    }
    pub fn get_new_id(&mut self) -> EnvironmentInternalSymbolKey {
        self.unique_keys += 1;
        self.unique_keys
    }
}
