use super::super::framework::EvalImpl;
use crate::gui_builder::node_registry::{NodeSpec, ParamKind};
use crate::gui_builder::nodes::{Node, NodeCategory, NodeGraph, NodeLibrary, NodeParams, Pin, PinType};
use crate::gui_builder::runtime::{RuntimeContext, RuntimeValue, ComponentContext};

pub struct GetValueNode;

impl EvalImpl for GetValueNode {
    fn evaluate(&self, _graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node, _pin_id: usize) -> Result<RuntimeValue, String> {
        let component_name = match &node.params {
            NodeParams::ComponentName(s) => s,
            _ => return Err("Missing component name".to_string()),
        };
        let val = ctx.get_value(component_name).unwrap_or(0.0);
        Ok(RuntimeValue::Float(val))
    }
}

impl super::super::framework::NodeDescription for GetValueNode {
    fn description(&self) -> &str {
        "Gets the value of a UI component (e.g., slider value, input text)."
    }
}

fn default_params() -> NodeParams {
    NodeParams::ComponentName(String::new())
}

fn pins(next_pin_id: &mut usize) -> Vec<Pin> {
    let mut pins = Vec::new();
    pins.push(Pin::new(*next_pin_id, PinType::Exec, true, ""));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::Exec, false, ""));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::Float, false, "value"));
    *next_pin_id += 1;
    pins
}

fn evaluate(graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node, pin_id: usize) -> Result<RuntimeValue, String> {
    GetValueNode.evaluate(graph, ctx, node, pin_id)
}

crate::register_node!(NodeSpec {
    id: "GetValue",
    display_name: "Get Value",
    documentation: "Gets the value of a UI component (e.g., slider value, input text).",
    category: NodeCategory::Action,
    library: NodeLibrary::Core,
    param_kind: ParamKind::ComponentSelector,
    default_params,
    pins,
    execute: None,
    evaluate: Some(evaluate),
});
