using System;
using System.Diagnostics;
using Minntech.Comm;
using Minntech.Common;
using Minntech.Logging;

namespace Minntech.SerialDevices
{
	/// <summary>
	/// Summary description for DSD201.
	/// </summary>
	public class DSD201: ISerialDevice	
	{
		private ICommDevice	_port			= null;
		private string		_buffer			= string.Empty;
		private Logging.Log	_log			= null;
		private string		_startDelimiter = Convert.ToString((byte)20);
		private string		_endDelimiter	= Convert.ToString((byte)13) + Convert.ToString((byte)10);

		public event RecordReceivedEventHandler	RecordReceived;

		public DSD201() 
		{
		}
		public void Dispose()
		{
			this._port.Dispose();
		}

		public ICommDevice Comm
		{
			get { return _port; }
			set 
			{ 
				if ( this._port != null )
					this._port.Dispose();
					
				this._port = value; 
				this._port.DataArrived += new DataArrivedEventHandler(this.CommDataArrived);
				this._port.CommError += new Comm.CommErrorEventHandler(this.CommDataError);
			}			
		}

		public Logging.Log Log
		{
			get { return this._log; }
			set { this._log = value; }
		}


		public SupportedSerialDevices Device
		{
			get { return SupportedSerialDevices.DSD201; }
		}

		#region events
		private void CommDataArrived ( object sender, DataArrivedEventArgs e )
		{
			try
			{
				// only write full records to the transmission queue

				// step1: add new data to any leftover from previous calls
				foreach ( byte chr in e.Data )
					this._buffer += Convert.ToString(chr);

				// step2: walk data looking for startofline and endofline indicators
				//		  NOTE: must begin walking at first startofline. Any characters
				//		  in the buffer but before the startofline are discarded
				
				bool done = false;
				
				while ( ( this._buffer.Length > 0 ) && ( ! done ) )
				{
					int start = this._buffer.IndexOf(this._startDelimiter);
					if ( start > 0 )
						//	discard anything before the start 
						this._buffer.Remove(0, start);
					
					if ( start < 0 )
						//	 if no start in string, we're done. Clear the buffer too. 
						this._buffer = string.Empty;
					else
					{
						//	find next end of line
						int end = this._buffer.IndexOf(this._endDelimiter);
						//	if no ends in string, we're done. But retain the record
						//	in case an end is on the way
						if ( end < 0 )
							done = true;
						else
						{
							//	we have a start and an end. Notify record consumer.
							string record = this._buffer.Substring(start, end + this._endDelimiter.Length);
							if ( record != string.Empty	)
							{
								this.RecordReceived(this, new RecordReceivedEventArgs(record));
								this._buffer.Remove(0, record.Length);
							}
						}
					}
				}
			}
			catch ( Exception ex )
			{
				this._log.WriteLog("CommDataArrived: " + ex.Message, EventLogEntryType.Error, Utilities.StringToByteArray(e.ToString()) );
			}
		}
		private void CommDataError   ( object sender, CommErrorEventArgs e )
		{
			// write error state message to log
			this._log.WriteLog("CommDataError: " + e.Message, EventLogEntryType.Error, Utilities.StringToByteArray(e.ToString()) );
		}
		#endregion
	}
}
