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

pub struct BoolLiteralNode;

impl EvalImpl for BoolLiteralNode {
    fn evaluate(&self, graph: &NodeGraph, ctx: &mut RuntimeContext, node: &Node, _pin_id: usize) -> Result<RuntimeValue, String> {
        // Check if input pin is connected - if so, use that value
        let input = eval_input(graph, ctx, node.id, "in")?;
        if !matches!(input, RuntimeValue::None) {
            return Ok(RuntimeValue::Bool(input.as_bool()));
        }
        
        // Otherwise use the parameter value
        if let NodeParams::BoolValue(val) = &node.params {
            Ok(RuntimeValue::Bool(*val))
        } else {
            Ok(RuntimeValue::Bool(false))
        }
    }
}

impl super::super::framework::NodeDescription for BoolLiteralNode {
    fn description(&self) -> &str {
        "Outputs a constant boolean value (True/False)."
    }
}

fn default_params() -> NodeParams {
    NodeParams::BoolValue(false)
}

fn pins(next_pin_id: &mut usize) -> Vec<Pin> {
    let mut pins = Vec::new();
    // Optional input - if connected, uses input value; otherwise uses param
    pins.push(Pin::new(*next_pin_id, PinType::Bool, true, "in"));
    *next_pin_id += 1;
    pins.push(Pin::new(*next_pin_id, PinType::Bool, false, "value"));
    *next_pin_id += 1;
    pins
}

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

crate::register_node!(NodeSpec {
    id: "BoolLiteral",
    display_name: "Boolean",
    documentation: "Outputs a constant boolean value (True/False).",
    category: NodeCategory::Data,
    library: NodeLibrary::Core,
    param_kind: ParamKind::BoolLiteral,
    default_params,
    pins,
    execute: None,
    evaluate: Some(evaluate),
});
