using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Ebel.Hardware.Communications;

namespace HwComWrapperNETGui.UserControls
{
    public partial class MsgCat03 : UserControl
    {
        #region Constructors and Destructors

        public MsgCat03()
        {
            this.InitializeComponent();

            this.button01.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetHwConfigClicked);
            this.button03.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetLicensesConfigClicked);
            this.button05.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetSwConfigClicked);
            this.button06.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetFPGAConfigClicked);
            this.button07.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetFPGAImagesInfoClicked);
            this.button08.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetMountStatesClicked);
            this.button09.Click += (sender, args) => this.HandleButtonClick(this.OnGetSetTransceiverStateClicked);
            this.button10.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetRtcClicked);
            this.button11.Click += (sender, args) => this.HandleButtonClick(this.ButtonSetRtcClicked);
            this.btGetActiveApp.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetActiveApplicationClicked);
            this.btSetActiveApp.Click += this.OnButtonSetActiveApplicationClicked;
            this.btGetAppVersion.Click += (sender, args) => this.HandleButtonClick(this.ButtonGetApplicationsVersionClicked);

            this.comboBoxTransceiverState.DataSource = Enum.GetValues(typeof(TransceiverState));
            this.comboBoxTransceiverSubState1.DataSource = Enum.GetValues(typeof(TransceiverSubState1));
            this.comboBoxTransceiverSubState2.DataSource = Enum.GetValues(typeof(TransceiverSubState2));
            this.cbApplicationType.DataSource = Enum.GetValues(typeof(ApplicationType));
            this.nudApplicationSlot.Value = 0;
            this.cbApplicationType.SelectedItem = ApplicationType.Application;
            this.tbCount.Text = Convert.ToString(this.listView1.Items.Count);            
        }

        #endregion

        #region Public Events

        /// <summary>
        ///     Occurs when the get button for COM_GetFPGAConfigReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetFPGAConfigClicked;

        /// <summary>
        ///     Occurs when the get button for COM_GetFPGAImagesReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetFPGAImagesInfoClicked;
        

        /// <summary>
        ///     Occurs when the get button for COM_GetHwConfigReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetHwConfigClicked;

        /// <summary>
        ///     Occurs when the get button for COM_GetLicenseConfigReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetLicensesConfigClicked;

        /// <summary>
        ///     Occurs when the get button for COM_GetSwConfigReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetSwConfigClicked;

        /// <summary>
        ///     Occurs when the get button for COM_GetFilySystemMountStatesReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetMountStatesClicked;

        /// <summary>
        ///     Occurs when the get button for COM_GetSetTransceiverStateReq was clicked. 
        /// </summary>
        public event EventHandler<GetSetTransceiverStateEventArgs> ButtonGetSetTransceiverStateClicked;

        /// <summary>
        ///     Occurs when the get button for COM_GetRtcReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetRtcClicked;

        /// <summary>
        ///     Occurs when the set button for COM_SetRtcReq was clicked. 
        /// </summary>
        public event EventHandler ButtonSetRtcClicked;

        /// <summary>
        ///     Occurs when the get button for COM_GetActiveApplicationReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetActiveApplicationClicked;

        /// <summary>
        ///     Occurs when the get button for COM_GetApplicationsVersionReq was clicked. 
        /// </summary>
        public event EventHandler ButtonGetApplicationsVersionClicked;

        /// <summary>
        ///     Occurs when the COM_SetActiveApplicationReq button was clicked.
        /// </summary>
        public event EventHandler <ActiveApplicationArgs> ButtonSetActiveApplicationClicked;

        #endregion

        #region Methods

        private void HandleButtonClick(EventHandler handler)
        {
            handler?.Invoke(this, EventArgs.Empty);
        }

        private void OnButtonSetActiveApplicationClicked(object sender, EventArgs e)
        {
            var handler = this.ButtonSetActiveApplicationClicked;

            if (handler == null)
            {
                return;
            }

            var applications = new Ebel.Hardware.Communications.Application[255];

           for(int i = 0; i < ApplicationList.Count; i++)
           {
                applications[i] = ApplicationList[i];
           }
            
            // Get Configurations
            var activeApplication = new ActiveApplication
            {
                Count = Convert.ToByte(this.listView1.Items.Count),
                Reserved = 0,
                Applications = applications,
            };
            handler(this, new ActiveApplicationArgs(activeApplication));
        }

        private void OnGetSetTransceiverStateClicked(object sender, EventArgs eventArgs)
        {
            var handler = this.ButtonGetSetTransceiverStateClicked;
            if (handler == null)
            {
                return;
            }

            byte channelNumber = (byte)numericUpDownTransceiverChannelNumber.Value;
            TransceiverState state;
            Enum.TryParse<TransceiverState>(comboBoxTransceiverState.SelectedValue.ToString(), out state);
            TransceiverSubState1 subState1;
            Enum.TryParse<TransceiverSubState1>(comboBoxTransceiverSubState1.SelectedValue.ToString(), out subState1);
            TransceiverSubState2 subState2;
            Enum.TryParse<TransceiverSubState2>(comboBoxTransceiverSubState2.SelectedValue.ToString(), out subState2);

            TransceiverStateInfo transceiverStateInfo = new TransceiverStateInfo(channelNumber, state, subState1, subState2);

            handler(this, new GetSetTransceiverStateEventArgs(transceiverStateInfo));
        }

        private void OnButtonAddApplicationClicked(object sender, EventArgs e)
        {
            // Get Application type
            var newApplication = new Ebel.Hardware.Communications.Application
            {
                Type = Convert.ToByte((ApplicationType)this.cbApplicationType.SelectedItem),
                ApplicationSlot = Convert.ToByte(this.nudApplicationSlot.Value)
            };

            // Check if already in list 
            if(ApplicationList.Exists(p => newApplication.Equals(p)))
            {
                // Info already in list
                return;
            }

            // Add to list
            ApplicationList.Add(newApplication);

            // Add to GUI List
            this.listView1.Items.Add(new ListViewItem(
                new[]
                {
                    Convert.ToString((ApplicationType)newApplication.Type),
                    Convert.ToString(newApplication.ApplicationSlot)
                })
            );

            // Update count
            this.tbCount.Text = Convert.ToString(this.listView1.Items.Count);
        }

        private void OnButtonRemoveApplicationClicked(object sender, EventArgs e)
        {
            var removedItems = new List<Ebel.Hardware.Communications.Application>();

            // Get selected item
            foreach (ListViewItem item in this.listView1.SelectedItems)
            {
                // Check subitem count = 2 Type, Slot
                if (item.SubItems.Count >= 2)
                {
                    // Creat temp application
                    var tempApplication = new Ebel.Hardware.Communications.Application();
                    // Get Text as Byte
                    if (Enum.TryParse<ApplicationType>(item.SubItems[0].Text, out ApplicationType applicationType) &&
                        byte.TryParse(item.SubItems[1].Text, out tempApplication.ApplicationSlot))
                    {
                        // Get app type in byte
                        tempApplication.Type = Convert.ToByte(applicationType);

                        // Remove Item From List
                        removedItems.AddRange(
                            ApplicationList.Where(p => p is Ebel.Hardware.Communications.Application application
                            && application.Type == tempApplication.Type && application.ApplicationSlot == tempApplication.ApplicationSlot)
                            );
                    }

                    // Remove Selected Items
                    listView1.Items.Remove(item);
                    ApplicationList.Remove(tempApplication);
                } 

                // Update Count
                this.tbCount.Text = Convert.ToString(this.listView1.Items.Count);
            }
        }

        private void OnButtonClearApplicationClicked(object sender, EventArgs e)
        {
            this.ApplicationList.Clear();
            this.listView1.Items.Clear();

            // Update Count
            this.tbCount.Text = Convert.ToString(this.listView1.Items.Count);
        }
        #endregion

        #region Constants and Fields
        private readonly List<Ebel.Hardware.Communications.Application> ApplicationList = new List<Ebel.Hardware.Communications.Application>();
        #endregion
    }
}