using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Windows.Forms;

namespace Inspectron.Settings.Windows.Configuration;

public partial class ListEditorDialog : Form
{
    private readonly Type _elementType;
    private readonly IList _originalList;
    private readonly IList _workingList;
    private readonly DefaultControlFactory _controlFactory;
    private readonly OptionsWindow _parentOptionsWindow;
    private readonly string _name;

    private ListBox _listBox;
    private Button _addButton;
    private Button _editButton;
    private Button _removeButton;
    private Button _okButton;
    private Button _cancelButton;

    public ListEditorDialog(Type elementType, IList originalList, DefaultControlFactory controlFactory, OptionsWindow parentOptionsWindow, string name)
    {
        _elementType = elementType;
        _originalList = originalList;
        _controlFactory = controlFactory;
        _parentOptionsWindow = parentOptionsWindow;
        _name = name;

        // Create a working copy of the list
        var listType = typeof(List<>).MakeGenericType(elementType);
        _workingList = (IList)Activator.CreateInstance(listType);
        
        foreach (var item in originalList)
        {
            _workingList.Add(CloneObject(item));
        }
        
        InitializeComponent();
        LoadListItems();
    }

    private void InitializeComponent()
    {
        this.Text = $"Edit {_name}";
        this.Size = new System.Drawing.Size(600, 400);
        this.StartPosition = FormStartPosition.CenterParent;
        this.FormBorderStyle = FormBorderStyle.FixedDialog;
        this.MaximizeBox = false;
        this.MinimizeBox = false;

        // Create controls
        _listBox = new ListBox
        {
            Location = new System.Drawing.Point(12, 12),
            Size = new System.Drawing.Size(460, 300),
            Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom
        };

        _addButton = new Button
        {
            Text = "Add",
            Location = new System.Drawing.Point(490, 12),
            Size = new System.Drawing.Size(75, 23),
            Anchor = AnchorStyles.Top | AnchorStyles.Right
        };

        _editButton = new Button
        {
            Text = "Edit",
            Location = new System.Drawing.Point(490, 45),
            Size = new System.Drawing.Size(75, 23),
            Anchor = AnchorStyles.Top | AnchorStyles.Right,
            Enabled = false
        };

        _removeButton = new Button
        {
            Text = "Remove",
            Location = new System.Drawing.Point(490, 78),
            Size = new System.Drawing.Size(75, 23),
            Anchor = AnchorStyles.Top | AnchorStyles.Right,
            Enabled = false
        };

        _okButton = new Button
        {
            Text = "OK",
            Location = new System.Drawing.Point(410, 330),
            Size = new System.Drawing.Size(75, 23),
            Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
            DialogResult = DialogResult.OK
        };

        _cancelButton = new Button
        {
            Text = "Cancel",
            Location = new System.Drawing.Point(490, 330),
            Size = new System.Drawing.Size(75, 23),
            Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
            DialogResult = DialogResult.Cancel
        };

        // Add event handlers
        _listBox.SelectedIndexChanged += ListBox_SelectedIndexChanged;
        _addButton.Click += AddButton_Click;
        _editButton.Click += EditButton_Click;
        _removeButton.Click += RemoveButton_Click;

        // Add controls to form
        this.Controls.AddRange(new Control[] { _listBox, _addButton, _editButton, _removeButton, _okButton, _cancelButton });
    }

    private void LoadListItems()
    {
        _listBox.Items.Clear();
        foreach (var item in _workingList)
        {
            _listBox.Items.Add(item?.ToString() ?? "(null)");
        }
    }

    private void ListBox_SelectedIndexChanged(object sender, EventArgs e)
    {
        bool hasSelection = _listBox.SelectedIndex >= 0;
        _editButton.Enabled = hasSelection;
        _removeButton.Enabled = hasSelection;
    }

    private void AddButton_Click(object sender, EventArgs e)
    {
        var defaultValue = GetDefaultValue(_elementType);
        using (var itemEditor = new ItemEditorDialog(_elementType, defaultValue, _controlFactory, _parentOptionsWindow))
        {
            if (itemEditor.ShowDialog(this) == DialogResult.OK)
            {
                _workingList.Add(itemEditor.GetEditedValue());
                LoadListItems();
                _listBox.SelectedIndex = _listBox.Items.Count - 1;
            }
        }
    }

    private void EditButton_Click(object sender, EventArgs e)
    {
        if (_listBox.SelectedIndex >= 0)
        {
            var selectedItem = _workingList[_listBox.SelectedIndex];
            using (var itemEditor = new ItemEditorDialog(_elementType, selectedItem, _controlFactory, _parentOptionsWindow))
            {
                if (itemEditor.ShowDialog(this) == DialogResult.OK)
                {
                    _workingList[_listBox.SelectedIndex] = itemEditor.GetEditedValue();
                    LoadListItems();
                }
            }
        }
    }

    private void RemoveButton_Click(object sender, EventArgs e)
    {
        if (_listBox.SelectedIndex >= 0)
        {
            int selectedIndex = _listBox.SelectedIndex;
            _workingList.RemoveAt(selectedIndex);
            LoadListItems();
            
            // Maintain selection if possible
            if (_listBox.Items.Count > 0)
            {
                _listBox.SelectedIndex = Math.Min(selectedIndex, _listBox.Items.Count - 1);
            }
        }
    }

    public IList GetEditedList()
    {
        return _workingList;
    }

    private object GetDefaultValue(Type type)
    {
        if (type.IsValueType)
        {
            return Activator.CreateInstance(type);
        }
        else if (type == typeof(string))
        {
            return "";
        }
        else
        {
            try
            {
                return Activator.CreateInstance(type);
            }
            catch
            {
                return null;
            }
        }
    }

    private object CloneObject(object obj)
    {
        if (obj == null) return null;
        
        var type = obj.GetType();
        if (type.IsValueType || type == typeof(string))
        {
            return obj;
        }
        
        // For complex objects, try to create a new instance and copy properties
        try
        {
            var clone = Activator.CreateInstance(type);
            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (prop.CanRead && prop.CanWrite)
                {
                    prop.SetValue(clone, prop.GetValue(obj));
                }
            }
            return clone;
        }
        catch
        {
            return obj; // Fallback to original object if cloning fails
        }
    }
}