using Inspectron.Settings;
using System.ComponentModel;
using System.Globalization;
using VisionBuilder.UI.Common;

namespace VisionBuilder.UI.IOCommander.Windows;

public class WindowsIOCommanderDebugViewSettings:ISettings
{
    public List<PinLabel> InputPinLabels { get; set; }
    public List<PinLabel> OutputPinLabels { get; set; }

    public void RegisterSettings(InspectronSettings settings)
    {
        settings.RegisterSimple(this, () => InputPinLabels, "IOCommander/DebugView", nameof(InputPinLabels));
        settings.RegisterSimple(this, () => OutputPinLabels, "IOCommander/DebugView", nameof(OutputPinLabels));
    }
}

public class PinLabel
{
    public int Pin { get; set; }
    public string Label { get; set; }

    public override string ToString()
    {
        return $"{Pin}:{Label}";
    }
}

public class PinLabelListConverter : 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 PinLabel
            if (context?.PropertyDescriptor?.PropertyType == typeof(PinLabel))
            {
                return ConvertFromString(context, culture, stringValue);
            }

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

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

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

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

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

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

        var parts = stringValue.Split(',');
        if (parts.Length == 2)
        {
            if (int.TryParse(parts[0], out int pin))
            {
                return new PinLabel
                {
                    Pin = pin,
                    Label = parts[1].Trim()
                };
            }
        }
        return null;
    }

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

        return $"{pinLabel.Pin},{pinLabel.Label}";
    }
}