using System;
using System.Windows.Forms;
using System.ComponentModel;


using nsAlienRFID2;


namespace Ex1cs
{
    public delegate void displayMessageDlgt(string msg);
    
    /// <summary>
	/// This application demonstrates synchronous communication with Alien reader using Com port.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{

		private clsReader mReader;
        private BackgroundWorker myWorker = null;


		#region Auto-generated code

		private System.Windows.Forms.GroupBox groupBox1;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.NumericUpDown numericUpDown1;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.ComboBox cboPorts;
		private System.Windows.Forms.Button btnGetReaderVersion;
		private System.Windows.Forms.Button btnGetReaderInfo;
		private System.Windows.Forms.Button btnDisconnect;
		private System.Windows.Forms.Button btnConnect;
		private System.Windows.Forms.RichTextBox textBox1;
        private ComboBox cboHostBaudRate;
        private Label label2;
        private ComboBox cboSerialBaudRate;
        private Label label4;
        private ToolTip toolTip1;
        private IContainer components;

		public Form1()
		{
			InitializeComponent();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				mReader.Dispose();
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            this.btnGetReaderVersion = new System.Windows.Forms.Button();
            this.btnConnect = new System.Windows.Forms.Button();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.cboHostBaudRate = new System.Windows.Forms.ComboBox();
            this.label2 = new System.Windows.Forms.Label();
            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
            this.cboPorts = new System.Windows.Forms.ComboBox();
            this.label3 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.btnGetReaderInfo = new System.Windows.Forms.Button();
            this.btnDisconnect = new System.Windows.Forms.Button();
            this.textBox1 = new System.Windows.Forms.RichTextBox();
            this.cboSerialBaudRate = new System.Windows.Forms.ComboBox();
            this.label4 = new System.Windows.Forms.Label();
            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
            this.groupBox1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
            this.SuspendLayout();
            // 
            // btnGetReaderVersion
            // 
            this.btnGetReaderVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.btnGetReaderVersion.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.btnGetReaderVersion.Location = new System.Drawing.Point(457, 103);
            this.btnGetReaderVersion.Name = "btnGetReaderVersion";
            this.btnGetReaderVersion.Size = new System.Drawing.Size(127, 28);
            this.btnGetReaderVersion.TabIndex = 1;
            this.btnGetReaderVersion.Text = "Get Reader &Version";
            this.btnGetReaderVersion.UseVisualStyleBackColor = false;
            this.btnGetReaderVersion.Click += new System.EventHandler(this.btnGetReaderVersion_Click);
            // 
            // btnConnect
            // 
            this.btnConnect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.btnConnect.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.btnConnect.Location = new System.Drawing.Point(457, 16);
            this.btnConnect.Name = "btnConnect";
            this.btnConnect.Size = new System.Drawing.Size(127, 27);
            this.btnConnect.TabIndex = 3;
            this.btnConnect.Text = "&Connect";
            this.btnConnect.UseVisualStyleBackColor = false;
            this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
            // 
            // groupBox1
            // 
            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.groupBox1.Controls.Add(this.cboHostBaudRate);
            this.groupBox1.Controls.Add(this.label2);
            this.groupBox1.Controls.Add(this.numericUpDown1);
            this.groupBox1.Controls.Add(this.cboPorts);
            this.groupBox1.Controls.Add(this.label3);
            this.groupBox1.Controls.Add(this.label1);
            this.groupBox1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.groupBox1.Location = new System.Drawing.Point(21, 222);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(563, 62);
            this.groupBox1.TabIndex = 5;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "Com Port";
            // 
            // cboHostBaudRate
            // 
            this.cboHostBaudRate.Anchor = System.Windows.Forms.AnchorStyles.Right;
            this.cboHostBaudRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cboHostBaudRate.FormattingEnabled = true;
            this.cboHostBaudRate.Items.AddRange(new object[] {
            "115200",
            "57600",
            "38400",
            "19200",
            "9600"});
            this.cboHostBaudRate.Location = new System.Drawing.Point(476, 23);
            this.cboHostBaudRate.Name = "cboHostBaudRate";
            this.cboHostBaudRate.Size = new System.Drawing.Size(64, 21);
            this.cboHostBaudRate.TabIndex = 13;
            this.toolTip1.SetToolTip(this.cboHostBaudRate, "Retrieves current baud rate value.");
            this.cboHostBaudRate.SelectedIndexChanged += new System.EventHandler(this.cboHostBaudRate_SelectedIndexChanged);
            // 
            // label2
            // 
            this.label2.Anchor = System.Windows.Forms.AnchorStyles.Right;
            this.label2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.label2.Location = new System.Drawing.Point(392, 27);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(87, 20);
            this.label2.TabIndex = 14;
            this.label2.Text = "Host Baud Rate:";
            // 
            // numericUpDown1
            // 
            this.numericUpDown1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
            this.numericUpDown1.Increment = new decimal(new int[] {
            100,
            0,
            0,
            0});
            this.numericUpDown1.Location = new System.Drawing.Point(283, 24);
            this.numericUpDown1.Maximum = new decimal(new int[] {
            2147483647,
            0,
            0,
            0});
            this.numericUpDown1.Minimum = new decimal(new int[] {
            60000,
            0,
            0,
            0});
            this.numericUpDown1.Name = "numericUpDown1";
            this.numericUpDown1.Size = new System.Drawing.Size(83, 20);
            this.numericUpDown1.TabIndex = 8;
            this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
            this.numericUpDown1.ThousandsSeparator = true;
            this.numericUpDown1.Value = new decimal(new int[] {
            60000,
            0,
            0,
            0});
            this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
            // 
            // cboPorts
            // 
            this.cboPorts.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cboPorts.FormattingEnabled = true;
            this.cboPorts.Items.AddRange(new object[] {
            "COM1:",
            "COM2:",
            "COM3:",
            "COM4:",
            "COM5:",
            "COM6:",
            "COM7:",
            "COM8:",
            "COM9:"});
            this.cboPorts.Location = new System.Drawing.Point(84, 23);
            this.cboPorts.Name = "cboPorts";
            this.cboPorts.Size = new System.Drawing.Size(64, 21);
            this.cboPorts.TabIndex = 11;
            this.toolTip1.SetToolTip(this.cboPorts, "Select a com port");
            this.cboPorts.SelectedIndexChanged += new System.EventHandler(this.cboPorts_SelectedIndexChanged);
            // 
            // label3
            // 
            this.label3.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.label3.Location = new System.Drawing.Point(22, 27);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(72, 20);
            this.label3.TabIndex = 12;
            this.label3.Text = "Port Name:";
            // 
            // label1
            // 
            this.label1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.label1.Location = new System.Drawing.Point(179, 27);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(112, 20);
            this.label1.TabIndex = 6;
            this.label1.Text = "Completion Timeout:";
            // 
            // btnGetReaderInfo
            // 
            this.btnGetReaderInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.btnGetReaderInfo.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.btnGetReaderInfo.Location = new System.Drawing.Point(457, 137);
            this.btnGetReaderInfo.Name = "btnGetReaderInfo";
            this.btnGetReaderInfo.Size = new System.Drawing.Size(127, 28);
            this.btnGetReaderInfo.TabIndex = 11;
            this.btnGetReaderInfo.Text = "Get Reader &Info";
            this.btnGetReaderInfo.UseVisualStyleBackColor = false;
            this.btnGetReaderInfo.Click += new System.EventHandler(this.btnGetReaderInfo_Click);
            // 
            // btnDisconnect
            // 
            this.btnDisconnect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.btnDisconnect.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.btnDisconnect.Location = new System.Drawing.Point(457, 49);
            this.btnDisconnect.Name = "btnDisconnect";
            this.btnDisconnect.Size = new System.Drawing.Size(127, 28);
            this.btnDisconnect.TabIndex = 13;
            this.btnDisconnect.Text = "&Disconnect";
            this.btnDisconnect.UseVisualStyleBackColor = false;
            this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click);
            // 
            // textBox1
            // 
            this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.textBox1.BackColor = System.Drawing.SystemColors.WindowText;
            this.textBox1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.textBox1.Location = new System.Drawing.Point(25, 16);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(407, 192);
            this.textBox1.TabIndex = 14;
            this.textBox1.Text = "";
            this.toolTip1.SetToolTip(this.textBox1, "Type in an Alien command and press [ENTER]");
            this.textBox1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyUp);
            // 
            // cboSerialBaudRate
            // 
            this.cboSerialBaudRate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.cboSerialBaudRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cboSerialBaudRate.FormattingEnabled = true;
            this.cboSerialBaudRate.Items.AddRange(new object[] {
            "115200",
            "57600",
            "38400",
            "19200",
            "9600"});
            this.cboSerialBaudRate.Location = new System.Drawing.Point(517, 191);
            this.cboSerialBaudRate.Name = "cboSerialBaudRate";
            this.cboSerialBaudRate.Size = new System.Drawing.Size(64, 21);
            this.cboSerialBaudRate.TabIndex = 15;
            this.toolTip1.SetToolTip(this.cboSerialBaudRate, "Sets Baud Rate on both reader and host, saves settings, and reconnects to the rea" +
                    "der.  This command may take a while...");
            // 
            // label4
            // 
            this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.label4.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
            this.label4.Location = new System.Drawing.Point(456, 195);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(72, 20);
            this.label4.TabIndex = 16;
            this.label4.Text = "Baud Rate:";
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.BackColor = System.Drawing.SystemColors.ControlText;
            this.ClientSize = new System.Drawing.Size(610, 309);
            this.Controls.Add(this.cboSerialBaudRate);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.btnDisconnect);
            this.Controls.Add(this.btnGetReaderInfo);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.btnConnect);
            this.Controls.Add(this.btnGetReaderVersion);
            this.MinimumSize = new System.Drawing.Size(618, 336);
            this.Name = "Form1";
            this.Text = "AlienRFID1.NET - Testing Serial Synchronously in C#";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
            this.groupBox1.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
            this.ResumeLayout(false);

		}

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
				Application.Run(new Form1());
		}

		#endregion


		private void Form1_Load(object sender, System.EventArgs e)
		{
            string exePath = Application.ExecutablePath;
            int idx = exePath.LastIndexOf("\\");
            if (idx != -1)
                AlienLog.Path = exePath.Substring(0, idx + 1);
            AlienLog.WriteLine(true, "Starting the 'Ex1-Serial Connection' application.");

            mReader = new clsReader(true);

            myWorker = new BackgroundWorker();
            myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
            myWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
            mReader.ForceUpdates = true;
            ManageGUI(false);
		}

        void mReader_DataReceived(string data)
        {
            displayText(data.Replace("\r", "[\\r]").Replace("\n", "[\\n]").Replace("\0", "[\\0]") + "\r\n");
        }

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

        private void addText(string s)
        {
            textBox1.Text += s;
            textBox1.Focus();
            textBox1.SelectAll();
            textBox1.ScrollToCaret();
            this.Cursor = Cursors.Default;
        }


        private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			if (mReader != null)
			{
                // If uncommented next line with a heavy tag-streaming on SERIAL
                // when closing application will hang indefinitely because of a bug in .NET's SerialPort.
                //mReader.Dispose();
			}
		}


		private void numericUpDown1_ValueChanged(object sender, System.EventArgs e)
		{
            if (mReader != null)
			    mReader.ComTimeOutInterval = (int)numericUpDown1.Value;	
		}

		private void cboPorts_SelectedIndexChanged(object sender, System.EventArgs e)
		{
            if (mReader != null)
			    mReader.SerialPort = cboPorts.Text;
		}

		
		private void ManageGUI(bool connected)
		{
			groupBox1.Enabled = !connected;
			btnConnect.Enabled = !connected;
			btnDisconnect.Enabled = connected;
            cboSerialBaudRate.Enabled = connected;
		}
		

		private void btnConnect_Click(object sender, System.EventArgs e)
		{		
			this.Cursor = Cursors.WaitCursor;
			mReader.InitOnCom();
			addText("\r\n" + mReader.Connect());
			ManageGUI(mReader.IsConnected);
            if (mReader.IsConnected)
            {
                cboSerialBaudRate.Text = mReader.SerialBaudRate;
                mReader.DataReceived += new CBaseReader.DataReceivedEventHandler(mReader_DataReceived);
            }
		}

		private void btnDisconnect_Click(object sender, System.EventArgs e)
		{	
			this.Cursor = Cursors.WaitCursor;
			if (mReader.IsConnected)
			{
                mReader.DataReceived -= new CBaseReader.DataReceivedEventHandler(mReader_DataReceived);
                // If uncommented next line with a heavy tag-streaming on SERIAL
                // when closing serial connection will hang indefinitely because of a bug in .NET's SerialPort.
                mReader.Disconnect();
				addText("\r\nSerial Port closed");
			}	
			else
				addText("\r\nNot Connected");

			ManageGUI(mReader.IsConnected);
		}

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

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

        private void cboHostBaudRate_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cboHostBaudRate.Enabled)
            {
                mReader.HostBaudRate = int.Parse(cboHostBaudRate.Text);
            }
        }
		
		private void textBox1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
		{
			String command = "";
			if (e.KeyCode == Keys.Enter)
			{
				command = textBox1.Lines[textBox1.Lines.GetUpperBound(0)-1];
				if (command.Length > 0)
				{
					try
					{
                        addText(mReader.SendReceive(command, false) + "\r\n");  // blocking call
                        //mReader.Send(command + "\r\n", true);   // asynchronous call
                    }
					catch (Exception ex)
					{
						addText("\r\n" + ex.Message);
					}
				}
			}
		}


        private void cboSerialBaudRate_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            string sBaudRate = cboSerialBaudRate.Text;
            if ((mReader != null) && (mReader.SerialBaudRate != sBaudRate))
            {
                myWorker.RunWorkerAsync(sBaudRate); // call this long synchronous command on a separate thread
            }
            while (myWorker.IsBusy)
            {
                Application.DoEvents();
            }
            cboHostBaudRate.Text = sBaudRate;

            this.Cursor = Cursors.Default;
        }


        void myWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string command = e.Argument as string;
            if (command == null)
            {
                try { mReader.SerialBaudRate = e.Argument as string; }
                catch (Exception ex) { e.Result = ex.Message; e.Cancel = true; }
            }
        }

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