using System;
using System.Drawing;
using System.Windows.Forms;

namespace B24SiemensEmulator
{
    public partial class MainForm : Form
    {
        private GroupBox inputGroupBox;
        private GroupBox outputGroupBox;
        private GroupBox controlGroupBox;
        private GroupBox statusGroupBox;

        // Input controls
        private CheckBox lifebitCheckBox;
        private CheckBox kameraStartCheckBox;
        private NumericUpDown materialnummerNumeric;
        private NumericUpDown artikelnummerBallNumeric;
        private NumericUpDown materialnummerFoilNumeric;
        private TextBox chargennummerTextBox;

        // Output controls (read-only)
        private Label lifebitResponseLabel;
        private Label kameraStartResponseLabel;
        private Label materialnummerResponseLabel;
        private Label artikelnummerBallResponseLabel;
        private Label materialnummerFoilResponseLabel;
        private Label chargennummerResponseLabel;

        // Control buttons
        private Button startStopButton;
        private Button saveConfigButton;
        private Button loadConfigButton;
        private Button applyButton;

        // Status controls
        private Label connectionStatusLabel;
        private Label errorMessageLabel;

        private bool isRunning = false;
        private SiemensTcpClient? tcpClient;
        private PLCPacket currentPacket = new PLCPacket();

        public MainForm()
        {
            InitializeComponent();
            InitializeTcpClient();
            WireUpEventHandlers();
            
            // Initialize current packet with form default values
            currentPacket = GetInputPacket();
        }

        private void InitializeTcpClient()
        {
            tcpClient = new SiemensTcpClient();
            tcpClient.GetPacketToSend = GetCurrentPacket;
            tcpClient.ConnectionStatusChanged += OnConnectionStatusChanged;
            tcpClient.ResponseReceived += OnResponseReceived;
            tcpClient.ErrorOccurred += OnErrorOccurred;
        }

        private void WireUpEventHandlers()
        {
            startStopButton.Click += OnStartStopButtonClick;
            saveConfigButton.Click += OnSaveConfigButtonClick;
            loadConfigButton.Click += OnLoadConfigButtonClick;
            applyButton.Click += OnApplyButtonClick;

            // Form closing event
            this.FormClosing += OnFormClosing;
        }

        private async void OnStartStopButtonClick(object? sender, EventArgs e)
        {
            if (tcpClient == null) return;

            if (!isRunning)
            {
                // Start
                var connected = await tcpClient.ConnectAsync();
                if (connected)
                {
                    tcpClient.StartSending();
                    SetRunningState(true);
                }
            }
            else
            {
                // Stop
                tcpClient.StopSending();
                await tcpClient.DisconnectAsync();
                SetRunningState(false);
            }
        }

        private void OnSaveConfigButtonClick(object? sender, EventArgs e)
        {
            var config = PacketConfiguration.FromPLCPacket(currentPacket);
            
            bool saved = ConfigurationManager.SaveConfiguration(config);
            if (saved)
            {
                MessageBox.Show("Current applied configuration saved successfully.", "Save Complete", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void OnLoadConfigButtonClick(object? sender, EventArgs e)
        {
            var config = ConfigurationManager.LoadConfiguration();
            if (config != null)
            {
                LoadConfigurationToForm(config);
                MessageBox.Show("Configuration loaded successfully. Click Apply to use the loaded values.", "Load Complete", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void OnApplyButtonClick(object? sender, EventArgs e)
        {
            currentPacket = GetInputPacket();
            
            // Provide visual feedback by briefly changing the button text
            applyButton.Text = "Applied!";
            applyButton.BackColor = Color.LightGreen;
            
            var timer = new System.Windows.Forms.Timer();
            timer.Interval = 1000; // 1 second
            timer.Tick += (s, args) =>
            {
                applyButton.Text = "Apply";
                applyButton.BackColor = SystemColors.Control;
                timer.Stop();
                timer.Dispose();
            };
            timer.Start();
        }

        private void LoadConfigurationToForm(PacketConfiguration config)
        {
            lifebitCheckBox.Checked = config.Lifebit;
            kameraStartCheckBox.Checked = config.KameraStart;
            materialnummerNumeric.Value = config.Materialnummer;
            artikelnummerBallNumeric.Value = config.ArtikelnummerBall;
            materialnummerFoilNumeric.Value = config.MaterialnummerFoil;
            chargennummerTextBox.Text = config.Chargennummer;
        }

        private void OnConnectionStatusChanged(bool connected)
        {
            UpdateConnectionStatus(connected);
            if (connected)
            {
                HideErrorMessage();
            }
        }

        private void OnResponseReceived(PLCPacket packet)
        {
            UpdateResponseDisplay(packet);
        }

        private void OnErrorOccurred(string error)
        {
            ShowErrorMessage(error);
        }

        private void OnFormClosing(object? sender, FormClosingEventArgs e)
        {
            tcpClient?.Dispose();
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();

            // Form properties
            this.Text = "B24 Siemens PLC Emulator";
            this.Size = new Size(800, 640);
            this.FormBorderStyle = FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.StartPosition = FormStartPosition.CenterScreen;

            // Status Group Box (Top)
            statusGroupBox = new GroupBox
            {
                Text = "Status",
                Location = new Point(12, 12),
                Size = new Size(760, 80)
            };

            connectionStatusLabel = new Label
            {
                Text = "Disconnected",
                Location = new Point(15, 25),
                Size = new Size(200, 20),
                Font = new Font("Microsoft Sans Serif", 9F, FontStyle.Bold)
            };

            errorMessageLabel = new Label
            {
                Text = "",
                Location = new Point(15, 50),
                Size = new Size(720, 20),
                ForeColor = Color.Red,
                Font = new Font("Microsoft Sans Serif", 8.25F)
            };

            statusGroupBox.Controls.Add(connectionStatusLabel);
            statusGroupBox.Controls.Add(errorMessageLabel);

            // Control Group Box
            controlGroupBox = new GroupBox
            {
                Text = "Controls",
                Location = new Point(12, 100),
                Size = new Size(760, 60)
            };

            startStopButton = new Button
            {
                Text = "Start",
                Location = new Point(15, 25),
                Size = new Size(100, 30),
                UseVisualStyleBackColor = true
            };

            saveConfigButton = new Button
            {
                Text = "Save Config",
                Location = new Point(130, 25),
                Size = new Size(100, 30),
                UseVisualStyleBackColor = true
            };

            loadConfigButton = new Button
            {
                Text = "Load Config",
                Location = new Point(245, 25),
                Size = new Size(100, 30),
                UseVisualStyleBackColor = true
            };

            controlGroupBox.Controls.Add(startStopButton);
            controlGroupBox.Controls.Add(saveConfigButton);
            controlGroupBox.Controls.Add(loadConfigButton);

            // Input Group Box (Left Panel)
            inputGroupBox = new GroupBox
            {
                Text = "Input Packet",
                Location = new Point(12, 180),
                Size = new Size(370, 390)
            };

            // Output Group Box (Right Panel)
            outputGroupBox = new GroupBox
            {
                Text = "Response Packet",
                Location = new Point(400, 180),
                Size = new Size(370, 390)
            };

            CreateInputControls();
            CreateOutputControls();

            // Add all controls to form
            this.Controls.Add(statusGroupBox);
            this.Controls.Add(controlGroupBox);
            this.Controls.Add(inputGroupBox);
            this.Controls.Add(outputGroupBox);

            this.ResumeLayout();
        }

        private void CreateInputControls()
        {
            int yPos = 30;
            int spacing = 45;

            // Lifebit
            var lifebitLabel = new Label
            {
                Text = "Lifebit:",
                Location = new Point(15, yPos),
                Size = new Size(80, 20)
            };
            lifebitCheckBox = new CheckBox
            {
                Location = new Point(120, yPos),
                Size = new Size(20, 20)
            };
            inputGroupBox.Controls.Add(lifebitLabel);
            inputGroupBox.Controls.Add(lifebitCheckBox);

            yPos += spacing;

            // KameraStart
            var kameraStartLabel = new Label
            {
                Text = "KameraStart:",
                Location = new Point(15, yPos),
                Size = new Size(80, 20)
            };
            kameraStartCheckBox = new CheckBox
            {
                Location = new Point(120, yPos),
                Size = new Size(20, 20)
            };
            inputGroupBox.Controls.Add(kameraStartLabel);
            inputGroupBox.Controls.Add(kameraStartCheckBox);

            yPos += spacing;

            // Materialnummer
            var materialnummerLabel = new Label
            {
                Text = "Materialnummer:",
                Location = new Point(15, yPos),
                Size = new Size(100, 20)
            };
            materialnummerNumeric = new NumericUpDown
            {
                Location = new Point(120, yPos),
                Size = new Size(120, 20),
                Minimum = int.MinValue,
                Maximum = int.MaxValue
            };
            inputGroupBox.Controls.Add(materialnummerLabel);
            inputGroupBox.Controls.Add(materialnummerNumeric);

            yPos += spacing;

            // ArtikelnummerBall
            var artikelnummerBallLabel = new Label
            {
                Text = "ArtikelnummerBall:",
                Location = new Point(15, yPos),
                Size = new Size(100, 20)
            };
            artikelnummerBallNumeric = new NumericUpDown
            {
                Location = new Point(120, yPos),
                Size = new Size(120, 20),
                Minimum = int.MinValue,
                Maximum = int.MaxValue
            };
            inputGroupBox.Controls.Add(artikelnummerBallLabel);
            inputGroupBox.Controls.Add(artikelnummerBallNumeric);

            yPos += spacing;

            // MaterialnummerFoil
            var materialnummerFoilLabel = new Label
            {
                Text = "MaterialnummerFoil:",
                Location = new Point(15, yPos),
                Size = new Size(100, 20)
            };
            materialnummerFoilNumeric = new NumericUpDown
            {
                Location = new Point(120, yPos),
                Size = new Size(120, 20),
                Minimum = int.MinValue,
                Maximum = int.MaxValue
            };
            inputGroupBox.Controls.Add(materialnummerFoilLabel);
            inputGroupBox.Controls.Add(materialnummerFoilNumeric);

            yPos += spacing;

            // Chargennummer
            var chargennummerLabel = new Label
            {
                Text = "Chargennummer:",
                Location = new Point(15, yPos),
                Size = new Size(100, 20)
            };
            chargennummerTextBox = new TextBox
            {
                Location = new Point(120, yPos),
                Size = new Size(120, 20),
                MaxLength = 5
            };
            inputGroupBox.Controls.Add(chargennummerLabel);
            inputGroupBox.Controls.Add(chargennummerTextBox);

            yPos += spacing;

            // Apply button
            applyButton = new Button
            {
                Text = "Apply",
                Location = new Point(120, yPos),
                Size = new Size(120, 30),
                UseVisualStyleBackColor = true,
                Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Bold)
            };
            inputGroupBox.Controls.Add(applyButton);
        }

        private void CreateOutputControls()
        {
            int yPos = 30;
            int spacing = 45;

            // Lifebit Response
            var lifebitResponseTitle = new Label
            {
                Text = "Lifebit:",
                Location = new Point(15, yPos),
                Size = new Size(80, 20)
            };
            lifebitResponseLabel = new Label
            {
                Text = "False",
                Location = new Point(120, yPos),
                Size = new Size(100, 20),
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = SystemColors.Control
            };
            outputGroupBox.Controls.Add(lifebitResponseTitle);
            outputGroupBox.Controls.Add(lifebitResponseLabel);

            yPos += spacing;

            // KameraStart Response
            var kameraStartResponseTitle = new Label
            {
                Text = "KameraStart:",
                Location = new Point(15, yPos),
                Size = new Size(80, 20)
            };
            kameraStartResponseLabel = new Label
            {
                Text = "False",
                Location = new Point(120, yPos),
                Size = new Size(100, 20),
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = SystemColors.Control
            };
            outputGroupBox.Controls.Add(kameraStartResponseTitle);
            outputGroupBox.Controls.Add(kameraStartResponseLabel);

            yPos += spacing;

            // Materialnummer Response
            var materialnummerResponseTitle = new Label
            {
                Text = "Materialnummer:",
                Location = new Point(15, yPos),
                Size = new Size(100, 20)
            };
            materialnummerResponseLabel = new Label
            {
                Text = "0",
                Location = new Point(120, yPos),
                Size = new Size(120, 20),
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = SystemColors.Control
            };
            outputGroupBox.Controls.Add(materialnummerResponseTitle);
            outputGroupBox.Controls.Add(materialnummerResponseLabel);

            yPos += spacing;

            // ArtikelnummerBall Response
            var artikelnummerBallResponseTitle = new Label
            {
                Text = "ArtikelnummerBall:",
                Location = new Point(15, yPos),
                Size = new Size(100, 20)
            };
            artikelnummerBallResponseLabel = new Label
            {
                Text = "0",
                Location = new Point(120, yPos),
                Size = new Size(120, 20),
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = SystemColors.Control
            };
            outputGroupBox.Controls.Add(artikelnummerBallResponseTitle);
            outputGroupBox.Controls.Add(artikelnummerBallResponseLabel);

            yPos += spacing;

            // MaterialnummerFoil Response
            var materialnummerFoilResponseTitle = new Label
            {
                Text = "MaterialnummerFoil:",
                Location = new Point(15, yPos),
                Size = new Size(100, 20)
            };
            materialnummerFoilResponseLabel = new Label
            {
                Text = "0",
                Location = new Point(120, yPos),
                Size = new Size(120, 20),
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = SystemColors.Control
            };
            outputGroupBox.Controls.Add(materialnummerFoilResponseTitle);
            outputGroupBox.Controls.Add(materialnummerFoilResponseLabel);

            yPos += spacing;

            // Chargennummer Response
            var chargennummerResponseTitle = new Label
            {
                Text = "Chargennummer:",
                Location = new Point(15, yPos),
                Size = new Size(100, 20)
            };
            chargennummerResponseLabel = new Label
            {
                Text = "",
                Location = new Point(120, yPos),
                Size = new Size(120, 20),
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = SystemColors.Control
            };
            outputGroupBox.Controls.Add(chargennummerResponseTitle);
            outputGroupBox.Controls.Add(chargennummerResponseLabel);
        }

        public PLCPacket GetInputPacket()
        {
            return new PLCPacket
            {
                Lifebit = lifebitCheckBox.Checked,
                KameraStart = kameraStartCheckBox.Checked,
                Materialnummer = (int)materialnummerNumeric.Value,
                ArtikelnummerBall = (int)artikelnummerBallNumeric.Value,
                MaterialnummerFoil = (int)materialnummerFoilNumeric.Value,
                Chargennummer = chargennummerTextBox.Text
            };
        }

        public PLCPacket GetCurrentPacket()
        {
            return currentPacket;
        }

        public void UpdateResponseDisplay(PLCPacket packet)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<PLCPacket>(UpdateResponseDisplay), packet);
                return;
            }

            lifebitResponseLabel.Text = packet.Lifebit.ToString();
            kameraStartResponseLabel.Text = packet.KameraStart.ToString();
            materialnummerResponseLabel.Text = packet.Materialnummer.ToString();
            artikelnummerBallResponseLabel.Text = packet.ArtikelnummerBall.ToString();
            materialnummerFoilResponseLabel.Text = packet.MaterialnummerFoil.ToString();
            chargennummerResponseLabel.Text = packet.Chargennummer;
        }

        public void UpdateConnectionStatus(bool connected)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<bool>(UpdateConnectionStatus), connected);
                return;
            }

            connectionStatusLabel.Text = connected ? "Connected" : "Disconnected";
            connectionStatusLabel.ForeColor = connected ? Color.Green : Color.Red;
        }

        public void ShowErrorMessage(string message)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string>(ShowErrorMessage), message);
                return;
            }

            errorMessageLabel.Text = message;
        }

        public void HideErrorMessage()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(HideErrorMessage));
                return;
            }

            errorMessageLabel.Text = "";
        }

        // Event handlers will be wired up later
        public Button StartStopButton => startStopButton;
        public Button SaveConfigButton => saveConfigButton;
        public Button LoadConfigButton => loadConfigButton;
        public bool IsRunning => isRunning;

        public void SetRunningState(bool running)
        {
            isRunning = running;
            startStopButton.Text = running ? "Stop" : "Start";
        }
    }
}