using System;
using System.Data;
using System.Data.OleDb;
using System.Data.AccessClient;
using System.Threading;
using Medivators.BusinessObjects;
using Medivators.Common;
using Medivators.Common.Enums;
using Medivators.Common.Logging;

namespace Medivators.Data
{
	public class AsynchronousExecute : IDisposable
	{
		public event SelectCompleteEventHandler SelectComplete;
		public event DataExceptionEventHandler DataException;
		public event InsertCompleteEventHandler InsertComplete;

		private long _id = Sequence.GetInstance().NextValue;

		public virtual void Dispose()
		{

		}
		public long DataOperationID
		{
			get { return _id; }
		}

		protected void Insert(string SQL)
		{
			Log.GetInstance().WriteLog(LogEntryType.DebugTrace, 
										"Executing Insert DataOperationID = " + 
										DataOperationID.ToString() +
										" SQL: " + SQL);
			Thread t = new Thread(ExecuteNonQuery);
			t.Start(SQL);
		}
		protected void Update(string SQL)
		{
			Log.GetInstance().WriteLog(LogEntryType.DebugTrace, 
										"Executing Update DataOperationID = " + 
										DataOperationID.ToString() +
										" SQL: " + SQL);
			Thread t = new Thread(ExecuteNonQuery);
			t.Start(SQL);
		}
		
		protected virtual void Select(string SQL, IDataMapper Mapper)
		{
			Log.GetInstance().WriteLog(LogEntryType.DebugTrace, 
										"Executing Select DataOperationID = " + 
										DataOperationID.ToString() +
										" SQL: " + SQL);
			object[] parms = new object[2];
			parms[0] = SQL;
			parms[1] = Mapper;
			Thread t = new Thread(ExecuteReader);
			t.Start(parms);
		}
		private void ExecuteNonQuery(object SQL)
		{
			try
			{
				int rows = 0;
				using (AccessCommand cmd = new AccessCommand())
				{
					Connection.GetInstance().Open();
					cmd.Connection = Connection.GetInstance();
					cmd.CommandText = (string)SQL;
					rows = cmd.ExecuteNonQuery();
					InsertComplete(this, new InsertCompleteEventArgs((string)SQL, rows, this.DataOperationID));
				}
			}
			catch (Exception ex)
			{
                ErrorHandler.GetInstance().LogException("AsynchronousExecute.ExecuteNonQuery: ", ex);
                DataException(this, new DataExceptionEventArgs((string)SQL, ex, this.DataOperationID));
			}
		}
		private void ExecuteReader(object Parameters)
		{
			// unpack parameters
			string sql = (string)((object[])Parameters)[0];
			IDataMapper mapper = (IDataMapper)((object[])Parameters)[1];
			
			try
			{

				using ( AccessCommand cmd = new AccessCommand())
				{
					Connection.GetInstance().Open();
					cmd.Connection = Connection.GetInstance();
					cmd.CommandText = sql;
					using (OleDbDataReader rdr = (OleDbDataReader)cmd.ExecuteReader())
					{
						mapper.Reader = rdr;
						rdr.Close();
					}
					SelectComplete(this, new SelectCompleteEventArgs(sql, mapper, this.DataOperationID));
				}
			}
			catch (Exception ex)
			{
                ErrorHandler.GetInstance().LogException("AsynchronousExecute.ExecuteReader: ", ex);
                DataException(this, new DataExceptionEventArgs(sql, ex, this.DataOperationID));
			}
		}
	}
}
