use crate::parser::interpreter::{DynamicFn, DynamicFnInfo, Interpreter};
use crate::parser::types::{FunctionValue, Value};
use std::sync::{Arc, Mutex};

pub fn type_bridge_fn(_interp: &mut Interpreter, mut args: Vec<Value>) -> Result<Value, String> {
    if args.len() != 1 {
        return Err(format!("type(...) => expected 1 argument, got {}", args.len()));
    }
    let val = args.remove(0);
    let tname = match &val {
        Value::Int(_)          => "int",
        Value::IntArray(_)     => "int_array",
        Value::Int2DArray(_)   => "int2d_array",
        Value::StrArray(_)     => "str_array",
        Value::KeyedArray(_)   => "keyed_array",
        Value::MixedArray(_)   => "mixed_array",
        Value::Function(_)     => "function",
        Value::Bool(_)         => "bool",
        Value::BoolArray(_)    => "bool_array",
        Value::Placeholder     => "placeholder",
        Value::SingleString(_) => "string",
        Value::Long(_)         => "long",
        Value::Float(_)        => "float",
        Value::FloatArray(_)   => "float_array",
        Value::Float2DArray(_) => "float2d_array",
        Value::Stream(_)       => "stream",
        Value::InkIterator(_)  => "ink_iterator",
        Value::InkTransform(_) => "ink_transform",
        Value::Tensor(_)       => "tensor",
        Value::Ref(arc_mutex)  => {
            // Recurse to inner value
            return type_bridge_fn(_interp, vec![arc_mutex.lock().unwrap().clone()]);
        }
    };
    Ok(Value::SingleString(tname.to_string()))
}

pub fn register_type(interp: &mut Interpreter) {
    let func_ref: DynamicFn = Arc::new(Mutex::new(type_bridge_fn));
    let info = DynamicFnInfo::new(func_ref, true);
    interp.register_dynamic_function_ex("type", info);
    interp.set_variable(
        "type",
        Value::Function(Box::new(FunctionValue::Named("type".to_string())))
    );
}
