using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

using nsAlienRFIDcf;


namespace nsAlienMobileSDK
{
    public partial class Form1 : Form
    {
        clsReader mReader;

        string msPreviousValue = "";

        private Thread mWorkerThread = null; //new Thread(new ThreadStart(DoWork));
        bool mbBusy = false;
        readonly object moBusyLock = new object();
        ManualResetEvent mWorkerFinishedMRE = new ManualResetEvent(false);
        readonly object moMyWorkerLock = new object();
        string mCurrentThreadParameter = null;
        readonly object moThreadParameterLock = new object();
        private frmProgressDlg myProgress = null;
        private string msNewBR = null;
        private const string WORKER_FINISHED = "Worker finished";

        private bool Busy
        {
            get { lock (moBusyLock) { return mbBusy; } }
            set { lock (moBusyLock) { mbBusy = value; } }
        }

        private string ThreadParameter
        {
            get { lock (moThreadParameterLock) { return mCurrentThreadParameter; } }
            set { lock (moThreadParameterLock) { mCurrentThreadParameter = value; } }
        }

        public delegate void displayMessageDlgt(string msg);
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Closing(object sender, CancelEventArgs e)
        {
            if (Busy)
            {
                try { mWorkerThread.Abort(); } catch { }
                mWorkerFinishedMRE.WaitOne(60000, true);
            }
            if (mReader != null)
                mReader.Dispose();

            mReader = null;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            mReader = new clsReader(true);
            AlienLog.WriteLine(false, "In Form1_Load().");
            string[] ports = AlienUtils.GetRegistryComs();
            if (ports != null)
            {
                for (int i = 0; i < ports.Length; i++)
                    cboPorts.Items.Add(ports[i]);

                cboPorts.SelectedIndex = 0;
            }
            cboHostBaudRate.SelectedIndex = 0;
            cboSerialBaudRate.SelectedIndex = 0;

            mWorkerThread = new Thread(new ThreadStart(DoWork));

            mReader.MessageReceived += new CBaseReader.MessageReceivedEventHandler(mReader_MessageReceived);
            mReader.Connected += new CBaseReader.ConnectedEventHandler(mReader_Connected);
            mReader.Disconnected += new CBaseReader.DisconnectedEventHandler(mReader_Disconnected);

            myProgress = new frmProgressDlg();
            myProgress.Closing += new CancelEventHandler(myProgress_Closing);
            ManageGUI(false);
        }

        void myProgress_Closing(object sender, CancelEventArgs e)
        {
            if (myProgress.mbSuccess)
                cboHostBaudRate.Text = msNewBR;
            else if (Busy)
                mWorkerThread.Abort();

            msNewBR = null;
            cboSerialBaudRate.Enabled = true;
            Cursor.Current = Cursors.Default;
        }

        void mReader_Disconnected(string data)
        {
            displayText(data.Replace("\r", "[\\r]").Replace("\n", "[\\n]").Replace("\0", "[\\0]") + "\r\n");
        }
        void mReader_Connected()
        {
            displayText("\r\nAdd here your CONNECTED_OK message.\r\n");
        }
        void mReader_DataReceived(string data)
        {
            displayText(data.Replace("\r", "[\\r]").Replace("\n", "[\\n]").Replace("\0", "[\\0]") + "\r\n");
        }
        void mReader_MessageReceived(string data)
        {
            displayText(data.Replace("\r", "[\\r]").Replace("\n", "[\\n]").Replace("\0", "[\\0]") + "\r\n");
        }

        private void ManageGUI(bool connected)
        {
            cboHostBaudRate.Enabled = !connected;
            cboPorts.Enabled = !connected;
            txtTimeout.Enabled = !connected;
            btnConnect.Enabled = !connected;
            label1.Enabled = !connected;
            label2.Enabled = !connected;
            label3.Enabled = !connected;

            btnDisconnect.Enabled = connected;
            cboSerialBaudRate.Enabled = connected;
            textBox1.Enabled = connected;
            cboCommand.Enabled = connected;
            label4.Enabled = connected;
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            cboSerialBaudRate.Text = cboHostBaudRate.Text;

            try
            {
                mReader.InitOnCom(
                    int.Parse(cboPorts.Text.Substring(3, 1)), 
                    int.Parse(cboHostBaudRate.Text));

                mReader.ComTimeOutInterval = int.Parse(txtTimeout.Text) * 1000;

                mWorkerFinishedMRE.Reset();
                ThreadParameter = null;

                addText("\r\n" + mReader.Connect());
                ManageGUI(mReader.IsConnected);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            Cursor.Current = Cursors.Default;
        }
        private void addText(string s)
        {
            if (s == WORKER_FINISHED)
                myProgress.Close();
            else
            {
                textBox1.Text += s.Replace("\0", "");
                cboCommand.Focus();
                Cursor.Current = Cursors.Default;
            }
        }

        private void displayText(String data)
        {
            try
            {
                if (this.InvokeRequired)
                {
                    object[] temp = { data };
                    this.Invoke(new displayMessageDlgt(displayText), temp);
                    return;
                }
                else
                {
                    addText(data.Replace("\0", ""));
                    ManageGUI(mReader.IsConnected);
                    return;
                }
            }
            catch (Exception ex)
            {
                AlienLog.WriteLine(true, "Exception in the DiscplayText: " + ex.Message);
            }
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            if ((mReader != null) && (mReader.IsConnected))
            {
                mReader.DataReceived -= new CBaseReader.DataReceivedEventHandler(mReader_DataReceived);
                mReader.Disconnect();
                addText("\r\nSerial Connection closed.");
            }
            else
                addText("\r\nNot Connected.");

            ManageGUI(false);
        }

        private void btnGetReaderInfo_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                addText("\r\n" + mReader.Info);
            }
            catch (Exception ex)
            {
                addText("\r\n" + ex.Message);
            }
        }

        private void btnGetReaderVersion_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                addText("\r\n" + mReader.ReaderVersion);
            }
            catch (Exception ex)
            {
                addText("\r\n" + ex.Message);
            }
        }


        
        void DoWork()
        {
            try
            {
                lock (moMyWorkerLock)
                {
                    Busy = true;
                    string baudRate = ThreadParameter;
                    if (baudRate != null)
                    {
                        try 
                        { 
                            mReader.SerialBaudRate = baudRate;                     
                            Busy = false;
                            myProgress.mbSuccess = true;
                            displayText(WORKER_FINISHED);   // to close myProgress
                        }
                        catch (Exception ex) { AlienLog.WriteLine(true, "myWorker() when changing reader's BaudRate caught: " + ex.Message); }
                    }
                    else
                    {
                        string msg = null;
                        try { msg = mReader.Connect(); }
                        catch (Exception ex) { AlienLog.WriteLine(true, "myWorker() when connecting caught: " + ex.Message); }
                    }
                    Busy = false;
                }
            }
            catch (Exception ex) { AlienLog.WriteLine(true, ex.Message); }
        }

        //void myWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        //{
        //    if ((!e.Cancelled) &&
        //        (e.Result != null) && 
        //        (e.Result is string))
        //    {
        //        addText(e.Result as string);
        //    }
        //}

        private void cboSerialBaudRate_Validating(object sender, CancelEventArgs e)
        {
        }

        private void btnExecute_Click(object sender, EventArgs e)
        {
            String command = cboCommand.Text.Trim();
            if (!string.IsNullOrEmpty(command))
            {
                textBox1.Text = "";
                try
                {
                    addText(mReader.SendReceive(command, false) + "\r\n");  // blocking call

                    //mReader.Send(command + "\r\n", true);   // asynchronous call

                    if (!cboCommand.Items.Contains(command))
                        cboCommand.Items.Add(command);
                }
                catch (Exception ex)
                {
                    addText("\r\n" + ex.Message);
                }
            }
        }

        private void cboSerialBaudRate_SelectedIndexChanged(object sender, EventArgs e)
        {
            string sBaudRate = cboSerialBaudRate.Text.Trim();
            if ((sender == null) || 
                (string.IsNullOrEmpty(sBaudRate)) ||
                (msPreviousValue == sBaudRate) ||
                (!mReader.IsConnected) ||
                (mReader.SerialBaudRate == sBaudRate))
                return;

            if (Busy)
            {
                if (msPreviousValue != null)
                    cboSerialBaudRate.Text = msPreviousValue;
                MessageBox.Show("Please wait for completion of a previous task.");
                return;
            }

            Cursor.Current = Cursors.WaitCursor;
            cboSerialBaudRate.Enabled = false;
            msNewBR = sBaudRate;
            ThreadParameter = sBaudRate;
            try { mWorkerThread.Start(); }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);    
                AlienLog.WriteLine(true, "cboSerialBaudRate_SelectedIndexChanged(): \r\n" + ex.Message);
            }
            myProgress.ShowDialog();
        }

        private void cboSerialBaudRate_GotFocus(object sender, EventArgs e)
        {
            msPreviousValue = cboSerialBaudRate.Text;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            textBox1.Text = "";
        }
    }
}