using System.Collections.Generic;
using System.Windows;

namespace Nodify.Calculator
{
    public class FunctionOperationViewModel : CalculatorOperationViewModel
    {
        private string _functionName = "Function";
        public string FunctionName
        {
            get => _functionName;
            set
            {
                if (SetProperty(ref _functionName, value))
                {
                    Title = value;
                }
            }
        }

        public List<FunctionParameterInfo> InputParameters { get; } = new List<FunctionParameterInfo>();
        public List<FunctionParameterInfo> OutputParameters { get; } = new List<FunctionParameterInfo>();

        private OperationViewModel InnerBegin { get; }
        private OperationViewModel InnerEnd { get; }

        public FunctionOperationViewModel()
        {
            // Add Begin and End nodes inside the inner calculator for flow-based editing
            InnerBegin = new SystemOperationViewModel
            {
                Title = "Begin",
                SystemOperationType = SystemOperations.BEGIN,
                Location = new Point(50, 150)
            };
            InnerBegin.Output.Add(new ConnectorViewModel { Title = "", Shape = ConnectorShape.Triangle, IsInput = false });

            InnerEnd = new SystemOperationViewModel
            {
                Title = "End",
                SystemOperationType = SystemOperations.END,
                Location = new Point(600, 150)
            };
            InnerEnd.Input.Add(new ConnectorViewModel { Title = "", Shape = ConnectorShape.Triangle });

            InnerCalculator.Operations.Add(InnerBegin);
            InnerCalculator.Operations.Add(InnerEnd);
        }

        public void ConfigureParameters(List<FunctionParameterInfo> inputs, List<FunctionParameterInfo> outputs)
        {
            InputParameters.Clear();
            InputParameters.AddRange(inputs);
            OutputParameters.Clear();
            OutputParameters.AddRange(outputs);

            // Add data output connectors to InnerBegin (these feed the inner flow with input values)
            foreach (var inp in inputs)
            {
                InnerBegin.Output.Add(new ConnectorViewModel
                {
                    Title = $"{inp.Name} ({inp.Type})",
                    Shape = ConnectorShape.Circle,
                    IsInput = false
                });

                // Also add an outer input connector on the function node
                Input.Add(new ConnectorViewModel
                {
                    Title = $"{inp.Name} ({inp.Type})"
                });
            }

            // Add data input connectors to InnerEnd (these collect inner flow results)
            foreach (var outp in outputs)
            {
                InnerEnd.Input.Add(new ConnectorViewModel
                {
                    Title = $"{outp.Name} ({outp.Type})",
                    Shape = ConnectorShape.Circle
                });

                // Also add an outer output connector on the function node
                Output.Add(new ConnectorViewModel
                {
                    Title = $"{outp.Name} ({outp.Type})",
                    IsInput = false
                });
            }
        }

        protected override void OnInputValueChanged()
        {
            PropagateInputsToInner();
        }

        public void PropagateInputsToInner()
        {
            // Propagate outer input values into the InnerBegin's data output connectors
            // The first output of InnerBegin is the flow triangle, data starts at index 1
            for (var i = 0; i < InputParameters.Count; i++)
            {
                var outerIndex = i; // outer Input: first is flow triangle (index 0), data starts at 1
                var innerIndex = i + 1; // InnerBegin Output: first is flow triangle, data starts at 1

                if (outerIndex + 1 < Input.Count && innerIndex < InnerBegin.Output.Count)
                {
                    InnerBegin.Output[innerIndex].Value = Input[outerIndex + 1].Value;
                }
            }
        }
    }

    public class FunctionParameterInfo
    {
        public string Name { get; set; } = string.Empty;
        public string Type { get; set; } = "string";
    }
}
