using System.Drawing;
using System.Windows.Forms;
using VisionBuilder.UI.IOCommander.Interfaces;

namespace VisionBuilder.UI.IOCommander.Windows
{
    public partial class WindowsIOCommanderDebugViewService : Form, IIOCommanderDebugViewService
    {
        private readonly WindowsIOCommanderDebugViewSettings _settings;
        private readonly Dictionary<int, PinIndicator> _inputPins = new();
        private readonly Dictionary<int, PinIndicator> _outputPins = new();
        private readonly object _lockObject = new object();
        private bool _isVisible = false;

        public WindowsIOCommanderDebugViewService(WindowsIOCommanderDebugViewSettings settings)
        {
            _settings = settings;
            InitializeComponent();
            InitializePinDisplay();
            
        }


        protected override void OnShown(EventArgs e)
        {
            this.TopMost = true;
            this.Focus();
            this.TopMost = true;
        }

        private void InitializePinDisplay()
        {
            // Configure form properties
            this.Text = "IOCommander Debug View";
            this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
            this.TopMost = true;
            this.TopLevel = true;
            this.ShowInTaskbar = false;
            this.StartPosition = FormStartPosition.Manual;
            this.Location = new Point(50, 50);
            this.Size = new Size(400, 350); // Made wider and adjusted height for 10 rows
            this.BackColor = Color.FromArgb(64, 64, 64);
            this.MinimizeBox = false;
            this.MaximizeBox = false;

            // Create pin indicators for input pins 1-10 and output pins 1-10 (10 rows, 2 columns)
            int pinSize = 24; // Increased from 18
            int spacing = 4; // Increased from 2
            int centerX = 200; // Center the graphics in the wider form
            int startY = 15; // Slightly more margin

            // Get label dictionaries for quick lookup
            var inputLabelDict = _settings.InputPinLabels?.ToDictionary(pl => pl.Pin, pl => pl.Label) ?? new Dictionary<int, string>();
            var outputLabelDict = _settings.OutputPinLabels?.ToDictionary(pl => pl.Pin, pl => pl.Label) ?? new Dictionary<int, string>();

            for (int row = 0; row < 10; row++) // Changed from 20 to 10
            {
                int inputPin = row + 1; // Input pins numbered 1-10
                int outputPin = row + 1; // Output pins numbered 1-10

                // Left column (input pins)
                var leftIndicator = new PinIndicator(inputPin, true)
                {
                    Location = new Point(centerX - pinSize - spacing * 2, startY + (row * (pinSize + spacing))),
                    Size = new Size(pinSize, pinSize)
                };
                _inputPins[inputPin] = leftIndicator;
                this.Controls.Add(leftIndicator);

                // Right column (output pins)
                var rightIndicator = new PinIndicator(outputPin, false)
                {
                    Location = new Point(centerX + spacing * 2, startY + (row * (pinSize + spacing))),
                    Size = new Size(pinSize, pinSize)
                };
                _outputPins[outputPin] = rightIndicator;
                this.Controls.Add(rightIndicator);

                // Input pin label (left side - label before pin number)
                string inputLabelText = inputLabelDict.ContainsKey(inputPin) ? $"{inputLabelDict[inputPin]} {inputPin}" : inputPin.ToString();
                var leftLabel = new Label
                {
                    Text = inputLabelText,
                    Location = new Point(5, startY + (row * (pinSize + spacing)) + 4), // Adjusted vertical alignment
                    Size = new Size(centerX - pinSize - spacing * 3 - 5, 16), // Increased height from 14
                    Font = new Font("Arial", 8, FontStyle.Bold), // Increased from 6
                    ForeColor = Color.White,
                    BackColor = Color.Transparent,
                    TextAlign = ContentAlignment.MiddleRight
                };
                this.Controls.Add(leftLabel);

                // Output pin label (right side - pin number followed by label)
                string outputLabelText = outputLabelDict.ContainsKey(outputPin) ? $"{outputPin} {outputLabelDict[outputPin]}" : outputPin.ToString();
                var rightLabel = new Label
                {
                    Text = outputLabelText,
                    Location = new Point(centerX + pinSize + spacing * 3, startY + (row * (pinSize + spacing)) + 4), // Adjusted vertical alignment
                    Size = new Size(this.Width - (centerX + pinSize + spacing * 3) - 10, 16), // Increased height from 14
                    Font = new Font("Arial", 8, FontStyle.Bold), // Increased from 6
                    ForeColor = Color.White,
                    BackColor = Color.Transparent,
                    TextAlign = ContentAlignment.MiddleLeft
                };
                this.Controls.Add(rightLabel);
            }
        }

        public void SetInputPinStatus(int pin, bool state)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() => SetInputPinStatus(pin, state)));
                return;
            }

            lock (_lockObject)
            {
                if (_inputPins.ContainsKey(pin))
                {
                    _inputPins[pin].SetState(state);
                }
            }
        }

        public void SetOutputPinStatus(int pin, bool state)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() => SetOutputPinStatus(pin, state)));
                return;
            }

            lock (_lockObject)
            {
                if (_outputPins.ContainsKey(pin))
                {
                    _outputPins[pin].SetState(state);
                }
            }
        }

        public void ShowDebugView()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(ShowDebugView));
                return;
            }

            lock (_lockObject)
            {
                if (!_isVisible)
                {
                    this.Show();
                    _isVisible = true;
                }
            }
        }


        private class PinIndicator : Control
        {
            private readonly int _pinNumber;
            private readonly bool _isInput;
            private bool _state = false;
            private readonly SolidBrush _activeBrush;
            private readonly SolidBrush _inactiveBrush;

            public PinIndicator(int pinNumber, bool isInput)
            {
                _pinNumber = pinNumber;
                _isInput = isInput;
                
                SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
                
                // Input pins: Green when active, dark gray when inactive
                // Output pins: Red when active, dark gray when inactive
                if (_isInput)
                {
                    _activeBrush = new SolidBrush(Color.Lime);
                    _inactiveBrush = new SolidBrush(Color.DarkGray);
                }
                else
                {
                    _activeBrush = new SolidBrush(Color.Red);
                    _inactiveBrush = new SolidBrush(Color.DarkGray);
                }
            }

            public void SetState(bool state)
            {
                if (_state != state)
                {
                    _state = state;
                    this.Invalidate();
                }
            }

            protected override void OnPaint(PaintEventArgs e)
            {
                var brush = _state ? _activeBrush : _inactiveBrush;
                e.Graphics.FillEllipse(brush, 0, 0, Width - 1, Height - 1);
                e.Graphics.DrawEllipse(Pens.Black, 0, 0, Width - 1, Height - 1);
            }

            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    _activeBrush?.Dispose();
                    _inactiveBrush?.Dispose();
                }
                base.Dispose(disposing);
            }
        }
    }
}
