using Inspectron.Settings;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using Inspectron.Settings.Attributes;
using VisionBuilder.UI.Common;

namespace VisionBuilder.UI.IOCommander.Settings
{
    public class IOCommanderCameraSettings:ISettings
    {
        public string CameraName { get; }


        public List<IOCommanderProcessingEvent> ProcessingEvents { get; set; } = [
            new (EProcessingEvent.SessionStarted),
            new (EProcessingEvent.SessionEnded),
            new (EProcessingEvent.ErrorOccurred),
            new (EProcessingEvent.GoodOccured),
            new (EProcessingEvent.ErrorsInSequenceAlarm),
        ];

        [SettingDescription(@"
Overrides pin values during test mode.
")]
        public List<IOCommanderPinAction> TestModeOverride { get; set; } = new List<IOCommanderPinAction>();

        public List<IOCommanderCommand> GPIOCommands { get; set; } = new List<IOCommanderCommand>();

        public IOCommanderCameraSettings(string cameraName)
        {
            CameraName = cameraName;
        }

        public void RegisterSettings(InspectronSettings settings)
        {
            foreach (var processingEvent in ProcessingEvents)
            {
                settings.RegisterSimple(processingEvent, () => processingEvent.Actions, CameraName + "/IOCommander/Outputs/"+processingEvent.Event.ToString(), nameof(processingEvent.Actions));
            }

            settings.RegisterSimple(this, () => TestModeOverride, CameraName + "/IOCommander/Outputs/" + nameof(TestModeOverride), nameof(TestModeOverride));

            settings.RegisterSimple(this, () => GPIOCommands, CameraName + "/IOCommander/Inputs", nameof(GPIOCommands));

        }
    }

    public class IOCommanderCommandListConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is string stringValue)
            {
                // Check if we're converting to a single IOCommanderCommand
                if (context?.PropertyDescriptor?.PropertyType == typeof(IOCommanderCommand))
                {
                    return ConvertFromString(context, culture, stringValue);
                }

                // Otherwise, convert to a list of IOCommanderCommand
                var commands = new List<IOCommanderCommand>();
                if (!string.IsNullOrEmpty(stringValue))
                {
                    var lines = stringValue.Split('\n', StringSplitOptions.RemoveEmptyEntries);

                    foreach (var line in lines)
                    {
                        var command = ConvertFromString(context, culture, line.Trim());
                        if (command != null)
                            commands.Add(command);
                    }
                }
                return commands;
            }
            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                // Handle single IOCommanderCommand
                if (value is IOCommanderCommand command)
                {
                    return ConvertToString(context, culture, command);
                }

                // Handle list of IOCommanderCommand
                if (value is List<IOCommanderCommand> commands)
                {
                    var lines = commands.Select(c =>
                        ConvertToString(context, culture, c)
                    ).Where(line => !string.IsNullOrEmpty(line));

                    return string.Join("\n", lines);
                }
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }

        /// <summary>
        /// Convert a single string to IOCommanderCommand
        /// </summary>
        private IOCommanderCommand ConvertFromString(ITypeDescriptorContext context, CultureInfo culture, string stringValue)
        {
            if (string.IsNullOrEmpty(stringValue))
                return null;

            var parts = stringValue.Split(',');
            if (parts.Length == 3)
            {
                if (int.TryParse(parts[0], out int pin) &&
                    bool.TryParse(parts[1], out bool onHigh) &&
                    Enum.TryParse<EGPIOCommand>(parts[2], out EGPIOCommand command))
                {
                    return new IOCommanderCommand
                    {
                        Pin = pin,
                        OnHigh = onHigh,
                        Command = command
                    };
                }
            }
            return null;
        }

        /// <summary>
        /// Convert a single IOCommanderCommand to string
        /// </summary>
        private string ConvertToString(ITypeDescriptorContext context, CultureInfo culture, IOCommanderCommand command)
        {
            if (command == null)
                return null;

            return $"{command.Pin},{command.OnHigh},{command.Command}";
        }
    }
}


