//! Eval implementations for array and map access functions

use anyhow::bail;
use hamelin_lib::func::defs::{GetArray, GetMap};

use crate::registry::EvalRegistry;
use crate::value::Value;

/// Register all access function eval implementations.
pub fn register(registry: &mut EvalRegistry) {
    // get(array, index) - returns array element at index
    registry.register_eval::<GetArray>(|mut bindings| {
        let array_value = bindings.take_by_name("array")?;
        let index_value = bindings.take_by_name("index")?;

        let index = index_value.require_int()?;
        let values = array_value.require_array()?;

        if index < 0 || index >= values.len() as i64 {
            bail!(
                "Array index {} out of bounds (array has {} elements)",
                index,
                values.len()
            );
        }

        Ok(values[index as usize].clone())
    });

    // get(map, key) - returns map value for key
    registry.register_eval::<GetMap>(|mut bindings| {
        let map_value = bindings.take_by_name("map")?;
        let key = bindings.take_by_name("key")?;

        let map = map_value.require_map()?;

        Ok(map.get(&key).cloned().unwrap_or(Value::Null))
    });
}
