using System;
using Medivators.Comm;
using Medivators.Common;
using Medivators.Common.Logging;
using Medivators.Common.Settings;

namespace Medivators.SerialDevices
{

	#region CommPortController interface
	
	public interface ICommPortController
	{
		ICommDevice						CommPort {get; set; }
		Log								Log		 {get; set; }
	}

	#endregion

	#region SerialDevice interface

	public delegate void RecordReceivedEventHandler	(ISerialDevice sender, RecordReceivedEventArgs	e);

	public class RecordReceivedEventArgs : System.EventArgs
	{
		private byte[] _record;
		public RecordReceivedEventArgs (byte[] Record)
		{
			this._record = Record;
		}
		public byte[] Record
		{
			get { return this._record; }
			set { this._record = value;}
		}
	}
	
	public enum SupportedSerialDevices
	{
		//TODO update with any newly support comm devices
		DSD201,
		DSD201SoftwareSimulation
	}

	public interface ISerialDevice : ICommPortController, IDisposable
	{
		SupportedSerialDevices				Device	{get; }	
		event RecordReceivedEventHandler	RecordReceived ;
	}

	
	#endregion

	#region specialized exception class

	public class SerialDeviceException : System.Exception
	{
		public CommPortSettings		CurrentSettings;
		public byte[]				CurrentBuffer;
		public CommEvent			CommEventType;

		#region constructors

		public SerialDeviceException(
			CommPortSettings Settings,
			byte[] Buffer,
			CommEvent EventType)
			: base()
		{
			CurrentSettings = Settings;
			CurrentBuffer = Buffer;
			CommEventType = EventType;
		}

		public SerialDeviceException(
			CommPortSettings Settings,
			byte[] Buffer,
			CommEvent EventType,
			string Message)
			: base(Message)
		{
			CurrentSettings = Settings;
			CurrentBuffer	= Buffer;
			CommEventType	= EventType;
		}
		
		public SerialDeviceException (	
			CommPortSettings Settings, 
			byte[]			 Buffer, 
			CommEvent		 EventType, 
			string			 Message, 
			Exception		 InnerException) : base(Message, InnerException)
		{
			CurrentSettings	= Settings;
			CurrentBuffer	= Buffer;
			CommEventType	= EventType;
		}
		#endregion
	}

	
	#endregion

	#region serial device transmissions

	public interface ISerialDeviceTransmission
	{
		SupportedSerialDevices SourceDevice {get;}
		byte[] Data {get; set; }
		string ToString();
	}
	public class SerialDeviceTransmission : ISerialDeviceTransmission
	{
		private SupportedSerialDevices _device;
		private byte[] _data;

		public SerialDeviceTransmission(SupportedSerialDevices SourceDevice, byte[] Data)
		{
			_device = SourceDevice;
			_data = Data;
		}
		public SupportedSerialDevices SourceDevice
		{
			get { return _device; }
		}
		public byte[] Data
		{
			get { return _data; }
			set { _data = value; }
		}
		public new string ToString()
		{
			string rtn = _device.ToString() + ", ";
			rtn += Utilities.ByteArrayToString(_data);
			return rtn;
		}
		public string ToString(bool MakePrintable)
		{
			string rtn = _device.ToString() + ", ";
			rtn += Utilities.ByteArrayToString(_data, MakePrintable);
			return rtn;
		}
	}

	#endregion

	public class SerialDevices
	{
		public SerialDevices()
		{
		}
		public static ISerialDevice SerialDevice( SupportedSerialDevices Device ) 
		{
			ISerialDevice rtnDevice = null;
			try
			{
				//TODO update with any newly support serial devices
				switch ( Device )
				{
					case SupportedSerialDevices.DSD201:
						rtnDevice = (ISerialDevice)(new DSD201());
						break;
					case SupportedSerialDevices.DSD201SoftwareSimulation:
						rtnDevice = (ISerialDevice)(new DSD201Simulation());
						break;
				}
				return rtnDevice;
			}
			catch ( Exception DeviceErr )
			{
				ErrorHandler.GetInstance().LogException("SerialDevices.SerialDevice", DeviceErr);
				throw DeviceErr;
			}
		}
	}
}

