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 System.Net;
using System.Threading;

namespace RateTableGUI
{
    public partial class RateTableWnd : Form
    {
        private RateTableController _Controller;


        private int Axis1_deg;
        private int Axis1_vel;

        private int Axis2_deg;
        private int Axis2_vel;

        private object Locker = new object();

        public void setController(RateTableController controller)
        {
            this._Controller = controller;
        }

        public int SelectedRateTable { get { return (this.RateTableSelectBox.SelectedIndex); } }
        public bool IsEthernetSelected { get { return (this.EthernetButton.Checked); } }
        public string IpAddress { get { return (this.IPaddressBox.Text); } }

        public int TcpPort
        { get 
            {
                int portNum;
                if (Int32.TryParse(this.IPportBox.Text, out portNum))
                    return portNum;
                else
                    return -1;
            }
        }

        public String ComPort
        {
            get { return (this.COMportList.SelectedItem == null ? "None" : this.COMportList.SelectedItem.ToString()); }
        }

        public String ComBaudrate
        {
            get { return (this.BaudrateList.SelectedItem.ToString()); }
        }

        public String ComDatabits
        {
            get { return (this.DatabitsList.SelectedItem.ToString()); }
        }

        public String ComStopbits
        {
            get { return (this.StopbitsList.SelectedItem.ToString()); }
        }

        public String ComParity
        {
            get { return (this.ParityList.SelectedItem.ToString()); }
        }

        public RateTableWnd()
        {
            InitializeComponent();

            this.RateTableSelectBox.SelectedIndex = 0;
            this.BaudrateList.SelectedItem = "9600";
            this.DatabitsList.SelectedItem = "8";
            this.StopbitsList.SelectedItem = "1";
            this.ParityList.SelectedItem = "None";

            textBoxSetPointDegAxis1.Text = "5";
            Axis1_deg = 5;

            textBoxSetPointVelAxis1.Text = "1";
            Axis1_vel = 1;

            textBoxSetPointDegAxis2.Text = "5";
            Axis2_deg = 5;

            textBoxSetPointVelAxis2.Text = "1";
            Axis2_vel = 1;
        }

        bool IsDigitsOnly(string str)
        {
            foreach (char c in str)
            {
                if (c < '0' || c > '9')
                    return false;
            }

            return true;
        }

        private void textBoxSetPointDegAxis1_KeyUp(object sender, KeyEventArgs e)
        {
            TextBox tb = (TextBox)sender;
            if (tb.Text == string.Empty)
                return;
            if (IsDigitsOnly(tb.Text))
            {
                Axis1_deg = Convert.ToInt32(tb.Text);
            }
        }

        private void textBoxSetPointDegAxis2_KeyUp(object sender, KeyEventArgs e)
        {
            TextBox tb = (TextBox)sender;
            if (tb.Text == string.Empty)
                return;
            if (IsDigitsOnly(tb.Text))
            {
                Axis2_deg = Convert.ToInt32(tb.Text);
            }
        }

        private void textBoxSetPointVelAxis1_KeyUp(object sender, KeyEventArgs e)
        {
            TextBox tb = (TextBox)sender;
            if (tb.Text == string.Empty)
                return;
            if (IsDigitsOnly(tb.Text))
            {
                Axis1_vel = Convert.ToInt32(tb.Text);
            }
        }

        private void textBoxSetPointVelAxis2_KeyUp(object sender, KeyEventArgs e)
        {
            TextBox tb = (TextBox)sender;
            if (tb.Text == string.Empty)
                return;
            if (IsDigitsOnly(tb.Text))
            {
                Axis2_vel = Convert.ToInt32(tb.Text);
            }
        }

        private void buttonMOVdAxis1_Click(object sender, EventArgs e)
        {
            if (_Controller != null)
            {
                _Controller.SetAxis1(Axis1_deg);
            }
        }

        private void buttonMOVdAxis2_Click(object sender, EventArgs e)
        {
            if (_Controller != null)
            {
                _Controller.SetAxis2(Axis2_deg);
            }
        }

        private void buttonMOVdvAxis1_Click(object sender, EventArgs e)
        {
            if (_Controller != null)
            {
                _Controller.SetAxis1(Axis1_deg, Axis1_vel);
            }
        }

        private void buttonMOVdvAxis2_Click(object sender, EventArgs e)
        {
            if (_Controller != null)
            {
                _Controller.SetAxis2(Axis2_deg, Axis2_vel);
            }
        }

        private void buttonSendCommand_Click(object sender, EventArgs e)
        {
            string[] lines = richTextBoxCommands.Text.Split('\n');
            if (lines[lines.Length - 1] != string.Empty)
            {
                if (_Controller != null)
                {
                    _Controller.SendCommandProvider(lines[lines.Length - 1]);
                    richTextBoxCommands.Text += Environment.NewLine;
                    richTextBoxCommands.Text += "reading response";
                    richTextBoxCommands.Text += string.Format("Response: {0}", _Controller.ReadCommandProvider());
                    richTextBoxCommands.Text += Environment.NewLine;
                }
            }
        }

        private void RateTableConnectButton_Click(object sender, EventArgs e)
        {
            this._Controller.Connect();
        }

        private void EthernetButton_CheckedChanged(object sender, EventArgs e)
        {
            if (this.EthernetButton.Checked == true)
            {
                this.IPaddressBox.Enabled = true;
                this.IPportBox.Enabled = true;

                this.SerialButton.Checked = false;
                this.COMportList.Enabled = false;
                this.BaudrateList.Enabled = false;
                this.DatabitsList.Enabled = false;
                this.StopbitsList.Enabled = false;
                this.ParityList.Enabled = false;
            }
        }

        private void SerialButton_CheckedChanged(object sender, EventArgs e)
        {
            if (this.SerialButton.Checked == true)
            {
                this.EthernetButton.Checked = false;
                this.IPaddressBox.Enabled = false;
                this.IPportBox.Enabled = false;

                this.COMportList.Enabled = true;
                this.BaudrateList.Enabled = true;
                this.DatabitsList.Enabled = true;
                this.StopbitsList.Enabled = true;
                this.ParityList.Enabled = true;
            }
        }

        public void UpdateConnectionControls()
        {
            bool enabled = _Controller.Status == RateTableController.DeviceStatus.NotConnected;
            this.EthernetButton.Enabled = enabled;
            this.IPaddressBox.Enabled = enabled;
            this.IPportBox.Enabled = enabled;

            this.SerialButton.Enabled = enabled;
            this.COMportList.Enabled = enabled;
            this.BaudrateList.Enabled = enabled;
            this.DatabitsList.Enabled = enabled;
            this.StopbitsList.Enabled = enabled;
            this.ParityList.Enabled = enabled;
            switch (_Controller.Status)
            {
                case RateTableController.DeviceStatus.NotConnected:
                    this.RateTableConnectButton.Enabled = true;
                    this.RateTableConnectButton.Text = "Connect";
                    this.statusStrip1.Text = "Disconnected";
                    EnableConfigAndWeather(false);
                    break;
                case RateTableController.DeviceStatus.Connecting:
                    this.RateTableConnectButton.Enabled = false;
                    this.RateTableConnectButton.Text = "Connecting";
                    this.statusStrip1.Text = "Connecting...";
                    EnableConfigAndWeather(false);
                    break;
                case RateTableController.DeviceStatus.Connected:
                    this.RateTableConnectButton.Enabled = true;
                    this.RateTableConnectButton.Text = "Disconnect";
                    this.statusStrip1.Text = "Connected";
                    EnableConfigAndWeather(true);
                    break;
            }
        }

        private void EnableConfigAndWeather(bool enabled)
        {
            this.RateTableConfGroupBox.Enabled = enabled;
            this.ValuesGroupBox.Enabled = enabled;
        }

        private void RateTableWnd_Load(object sender, EventArgs e)
        {
            this.COMportList.Items.Clear();
            this.COMportList.Items.AddRange(this._Controller.getAvailableCOMs());
        }

        public void UpdateValues(float innerZero, float innerVel, int innerStatus, float innerRef, float innerActPos, float innerAcc,
                                float outerZero, float outerVel, int outerStatus, float outerRef, float outerActPos, float outerAcc)
        {
            if (labelInnerZeroPosition.InvokeRequired)
            {
                labelInnerZeroPosition.Invoke(new MethodInvoker(delegate { labelInnerZeroPosition.Text = string.Format("{0:N2}", innerZero); }));
                labelInnerVelocity.Invoke(new MethodInvoker(delegate { labelInnerVelocity.Text = string.Format("{0:N2}", innerVel); }));
                labelInnerStatus.Invoke(new MethodInvoker(delegate { labelInnerStatus.Text = string.Format("{0}", innerStatus); }));
                labelInnerRefPosition.Invoke(new MethodInvoker(delegate { labelInnerRefPosition.Text = string.Format("{0:N2}", innerRef); }));
                labelInnerActPosition.Invoke(new MethodInvoker(delegate { labelInnerActPosition.Text = string.Format("{0:N2}", innerActPos); }));
                labelInnerActAcceleration.Invoke(new MethodInvoker(delegate { labelInnerActAcceleration.Text = string.Format("{0:N2}", innerAcc); }));

                labelOuterZeroPosition.Invoke(new MethodInvoker(delegate { labelOuterZeroPosition.Text = string.Format("{0:N2}", outerZero); }));
                labelOuterVelocity.Invoke(new MethodInvoker(delegate { labelOuterVelocity.Text = string.Format("{0:N2}", outerVel); }));
                labelOuterStatus.Invoke(new MethodInvoker(delegate { labelOuterStatus.Text = string.Format("{0}", outerStatus); }));
                labelOuterRefPosition.Invoke(new MethodInvoker(delegate { labelOuterRefPosition.Text = string.Format("{0:N2}", outerRef); }));
                labelOuterActPosition.Invoke(new MethodInvoker(delegate { labelOuterActPosition.Text = string.Format("{0:N2}", outerActPos); }));
                labelOuterActAcceleration.Invoke(new MethodInvoker(delegate { labelOuterActAcceleration.Text = string.Format("{0:N2}", outerAcc); }));
            }
            else
            { 
            
            }
        }
    }
}
