use super::super::framework::{EvalImpl, eval_input_string};
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};

pub struct JsonSplitStringNode;

impl EvalImpl for JsonSplitStringNode {
    fn evaluate(&self, graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node, pin_id: usize) -> Result<RuntimeValue, String> {
        let input_string = eval_input_string(graph, ctx, node.id, "string")?;
        let delimiter = eval_input_string(graph, ctx, node.id, "delimiter")?;
        
        // Default delimiter is comma if empty
        let delim = if delimiter.is_empty() { "," } else { &delimiter };
        
        // Split and trim each item
        let items: Vec<RuntimeValue> = input_string
            .split(delim)
            .map(|s| s.trim().to_string())
            .filter(|s| !s.is_empty())
            .map(|s| RuntimeValue::String(s))
            .collect();
        
        let count = items.len();
        
        // Find output pin name to determine which value to return
        if let Some(pin) = node.pins.iter().find(|p| p.id == pin_id) {
            match pin.name.as_str() {
                "count" => Ok(RuntimeValue::Float(count as f32)),
                _ => Ok(RuntimeValue::Array(items)),
            }
        } else {
            Ok(RuntimeValue::Array(items))
        }
    }
}

impl super::super::framework::NodeDescription for JsonSplitStringNode {
    fn description(&self) -> &str {
        "Splits a delimited string (e.g., comma-separated) into an array of strings."
    }
}

fn default_params() -> NodeParams {
    NodeParams::None
}

fn pins(next_pin_id: &mut usize) -> Vec<Pin> {
    let mut pins = Vec::new();
    pins.push(Pin::new(*next_pin_id, PinType::String, true, "string"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::String, true, "delimiter"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::Array, false, "array"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::Float, false, "count"));
    *next_pin_id += 1;
    pins
}

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

crate::register_node!(NodeSpec {
    id: "JsonSplitString",
    display_name: "Split String",
    documentation: "Splits a delimited string (e.g., comma-separated) into an array of strings.",
    category: NodeCategory::Data,
    library: NodeLibrary::Json,
    param_kind: ParamKind::None,
    default_params,
    pins,
    execute: None,
    evaluate: Some(eval),
});
