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

pub struct SetComboBoxItemsNode;

impl NodeImpl for SetComboBoxItemsNode {
    fn execute(&self, graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node) -> Result<Option<usize>, String> {
        let component_name = match &node.params {
            NodeParams::ComponentName(name) => name,
            _ => return Err("SetComboBoxItems node missing component name parameter".to_string()),
        };

        let items_value = eval_input(graph, ctx, node.id, "items")?;
        let items = match items_value {
            RuntimeValue::Array(arr) => arr.into_iter().map(|v| v.as_string()).collect::<Vec<_>>(),
            RuntimeValue::String(s) => {
                if s.is_empty() {
                    Vec::new()
                } else {
                    s.split(',').map(|p| p.trim().to_string()).collect()
                }
            }
            other => vec![other.as_string()],
        };

        let _ = ctx.set_combobox_items(component_name, items);
        get_default_exec_out(node)
    }
}

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::Array, true, "items"));
    *next_pin_id += 1;
    pins
}

fn exec(graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node, _stack: &mut ExecutionStack) -> Result<Option<usize>, String> {
    SetComboBoxItemsNode.execute(graph, ctx, node)
}

crate::register_node!(NodeSpec {
    id: "SetComboBoxItems",
    display_name: "Set ComboBox Items",
    documentation: "Dynamically sets the list of items in a ComboBox from an array.",
    category: NodeCategory::Action,
    library: NodeLibrary::Core,
    param_kind: ParamKind::ComponentSelector,
    default_params,
    pins,
    execute: Some(exec),
    evaluate: None,
});
