using System;
using System.Data.OleDb;
using System.Collections.Generic;
using System.Text;
using Medivators.Common;

namespace Medivators.BusinessObjects
{
	public class CycleReportDataMapper : IDataMapper
	{
		private List<IBusinessObject> _list = null;

		public List<IBusinessObject> BusinessObjectCollection
		{
			get { return _list; }
		}
		public OleDbDataReader Reader
		{
			set 
			{
				//	the returned data reader is denormalized, containing
				//	cycle records and the associated log records. 

				if (_list == null)
					_list = new List<IBusinessObject>();

				Dictionary<string, IBusinessObject> reports = new Dictionary<string, IBusinessObject>();

				try
				{
					while (value.Read())
					{
						CycleReport rpt = new CycleReport();
						IDeviceRecord rec = null;

						//  get record type to determine what 
						//	type of log record to instantiate
						DeviceRecordTypes recType = (DeviceRecordTypes)Enum.Parse(typeof(DeviceRecordTypes), (string)value["RecordType"]);
						switch (recType)
						{
							case DeviceRecordTypes.CycleEnd:
							case DeviceRecordTypes.CycleStart:
							case DeviceRecordTypes.LogRecord:
								rec = new DSD201EventRecord();
								break;
							default:
								rec = new TimestampedHeaderRecord();
								break;
						}

						#region for loop & switch statement reads fields into records

						for (int fldNo = 0; fldNo < value.FieldCount; fldNo++)
						{
							if (!value.IsDBNull(fldNo))
							{

								switch (value.GetName(fldNo).ToLower())
								{
									//	keys are not listed as classes calculates their own keys
									//	fields that exist in both record types are both listed 
									//	under the same case
									case "cr.machineid":
										rpt.MachineID = value.GetInt32(fldNo);
										((DeviceRecord)rec).MachineID = rpt.MachineID;
										break;
									case "cr.station":
										rpt.Station = value.GetString(fldNo);
										((DeviceRecord)rec).Station = rpt.Station;
										break;
									case "starttimestamp":
										rpt.StartTimestamp = value.GetDateTime(fldNo);
										break;
									case "endtimestamp":
										rpt.EndTimestamp = value.GetDateTime(fldNo);
										break;
									case "cyclecount":
										rpt.CycleCount = value.GetInt16(fldNo);
										break;
									case "disinfectantcyclecount":
										rpt.DisinfectantCycleCount = value.GetInt16(fldNo);
										break;
									case "operatorid":
										rpt.OperatorID = value.GetInt32(fldNo);
										break;
									case "patientid":
										rpt.PatientID = value.GetInt32(fldNo);
										break;
									case "physicianid":
										rpt.PhysicianID = value.GetInt32(fldNo);
										break;
									case "scopeid":
										rpt.ScopeID = value.GetInt32(fldNo);
										break;
									case "ssgratio":
										rpt.SSGRatio = value.GetString(fldNo);
										break;
									case "recordtype":
										((DeviceRecord)rec).RecordType = recType;
										break;
									case "isalarm":
										((DeviceRecord)rec).IsAlarm = value.GetBoolean(fldNo);
										break;
									case "lognumber":
										((DeviceRecord)rec).LogNumber = value.GetInt32(fldNo);
										break;
									case "text":
										((DeviceRecord)rec).Text = value.GetString(fldNo);
										break;
									case "program":
										((DSD201EventRecord)rec).Program = value.GetInt16(fldNo);
										break;
									case "data":
										((TimestampedHeaderRecord)rec).Data = value.GetString(fldNo);
										break;
									case "timestamp":
										((ITimestampedDeviceRecord)rec).Timestamp = value.GetDateTime(fldNo);
										break;
								}
							}
						}
						#endregion

						string rptKey = rpt.Key;
						//	see if this cycle report is already in temp accumulator
						if (!reports.ContainsKey(rptKey))
							reports.Add(rptKey, rpt);
						//	apply log record
						((CycleReport)reports[rptKey]).LogRecords.Add(rec);
					}

					//	read temp accumular into return property holder
					if (_list == null)
						_list = new List<IBusinessObject>();
					else
						_list.Clear();

					foreach (IBusinessObject obj in reports.Values)
						_list.Add(obj);
				}
				catch (Exception ex)
				{
					ErrorHandler.GetInstance().LogException("CycleReportDataMapper.Reader error: ", ex);
				}
			}
		}
		public void Dispose()
		{
			if ( _list != null )
				_list.Clear();
		}
		public object Data
		{
			get { return (object)_list; }
		}
	}
}
