context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.IO;
  using Timok.Logger;
  using Timok.Rbr.BLL.Managers;
  using Timok.Rbr.Core;
  using Timok.Rbr.Core.Config;
  using Timok.Rbr.DAL.RbrDatabase;
  using Timok.Rbr.DTO;
  using WinFormsEx;
  
  namespace Timok.Rbr.BLL.Inventory {
  	public class InventoryController {
  		public const char FieldDelimiter = '\t';
  
  		#region Getters
  
  		public static BatchDto[] GetGeneratedBatchesByServiceId(short pServiceId) {
  			var _list = new ArrayList();
  			using (var _db = new Rbr_Db()) {
  				InventoryLotRow[] _inventoryLotRows = _db.InventoryLotCollection.GetByService_id(pServiceId);
  				foreach (var _inventoryLotRow in _inventoryLotRows) {
  					GenerationRequestRow[] _generationRequestRows = _db.GenerationRequestCollection.GetByLot_id(_inventoryLotRow.Lot_id);
  					foreach (var _generationRequestRow in _generationRequestRows) {
  						BatchRow[] _batchRows = _db.BatchCollection.GetGeneratedByRequestId(_generationRequestRow.Request_id);
  						_list.AddRange(MapToBatches(_batchRows, _inventoryLotRow, _generationRequestRow));
  					}
  				}
  			}
  			return (BatchDto[]) _list.ToArray(typeof (BatchDto));
  		}
  
  		public static BatchDto[] GetBatchesByInventoryStatusServiceIdCustomerAcctId(InventoryStatus pInventoryStatus, short pServiceId, short pCustomerAcctId) {
  			var _list = new ArrayList();
  			using (var _db = new Rbr_Db()) {
  				var _inventoryLotRows = _db.InventoryLotCollection.GetByService_id(pServiceId);
  				foreach (var _inventoryLotRow in _inventoryLotRows) {
  					var _generationRequestRows = _db.GenerationRequestCollection.GetByLot_id(_inventoryLotRow.Lot_id);
  					foreach (var _generationRequestRow in _generationRequestRows) {
  						var _batchRows = _db.BatchCollection.GetByInventoryStatusCustomerAcctIdRequestId(pInventoryStatus, pCustomerAcctId, _generationRequestRow.Request_id);
  						_list.AddRange(MapToBatches(_batchRows, _inventoryLotRow, _generationRequestRow));
  					}
  				}
  			}
  			return (BatchDto[]) _list.ToArray(typeof (BatchDto));
  		}
  
  		public static RetailAccountDto GetAcct(int pRetailAcctId) {
  			using (var _db = new Rbr_Db()) {
  				//-- get account
  				var _retailAcct = RetailAccountManager.Instance.GetAcct(_db, pRetailAcctId);
  				if (_retailAcct == null) {
  					throw new RbrException(RbrResult.POSA_AcctNotFound, string.Empty);
  				}
  				return _retailAcct;
  			}
  		}
  
  		#endregion Getters
  
  		#region Actions
  
  		public static bool AddLot(RetailAccountGenResponse pResponse, PersonDto pPerson) {
  			bool _result = false;
  
  			using (var _db = new Rbr_Db()) {
  				_db.BeginTransaction();
  
  				try {
  					InventoryLotRow _lotRow = _db.InventoryLotCollection.GetByServiceIdDenomination(pResponse.Request.ServiceId, pResponse.Request.Denomination);
  					if (_lotRow == null) {
  						_lotRow = new InventoryLotRow();
  						_lotRow.Service_id = pResponse.Request.ServiceId;
  						_lotRow.Denomination = pResponse.Request.Denomination;
  						_db.InventoryLotCollection.Insert(_lotRow);
  					}
  
  					var _requestRow = new GenerationRequestRow();
  					_requestRow.Date_requested = DateTime.Now;
  					_requestRow.Date_completed = DateTime.Now;
  					_requestRow.Date_to_process = DateTime.Now;
  					_requestRow.Number_of_batches = pResponse.Request.NumberOfBatches;
  					_requestRow.Batch_size = pResponse.Request.BatchSize;
  					_requestRow.Lot_id = _lotRow.Lot_id;
  					_db.GenerationRequestCollection.Insert(_requestRow);
  
  					foreach (var _batch in pResponse.BatchList) {
  						var _batchRow = new BatchRow();
  						_batchRow.Batch_id = _batch.BatchId;
  						_batchRow.First_serial = _batch.FirstSerial;
  						_batchRow.Last_serial = _batch.LastSerial;
  						_batchRow.Request_id = _requestRow.Request_id;
  						//_batchRow.Box_id = ???? xxx; NOT SET for now
  						//_batchRow.Customer_acct_id = WILL BE SET ON LOAD/ACTIVATE;
  						_batchRow.InventoryStatus = InventoryStatus.Generated;
  						_db.BatchCollection.Insert(_batchRow);
  
  						logInventoryHistory(_db, pPerson, DateTime.Now, _lotRow.Service_id, _lotRow.Denomination, _batchRow.Batch_id, _batchRow.NumberOfCards, InventoryCommand.Generate, 0, //CustomerAcctId - N/A FOR THIS COMMAND
  						                    0, //ResellerPartnerId - N/A FOR THIS COMMAND
  						                    0 //ResellerAgentId - N/A FOR THIS COMMAND
  							);
  					}
  					_db.CommitTransaction();
  					_result = true;
  				}
  				catch (Exception _ex) {
  					_db.RollbackTransaction();
  					TimokLogger.Instance.LogRbr(LogSeverity.Critical, "InventoryController.AddLot", string.Format("Exception: {0}", _ex));
  				}
  			}
  
  			return _result;
  		}
  
  		public static void ExecuteCommand(object sender, DoWorkEventArgs pEvtArg) {
  			using (var _db = new Rbr_Db()) {
  				_db.BeginTransaction();
  
  				var _backgroundWorker = (BackgroundWorker) sender;
  				var _inventoryCommandRequest = (InventoryCommandRequest) pEvtArg.Argument;
  
  				_backgroundWorker.ReportStatus("Executing Batch Command: [" + _inventoryCommandRequest.InventoryCommand + "]");
  
  				switch (_inventoryCommandRequest.InventoryCommand) {
  					case InventoryCommand.Load:
  						executeLoadCommand(_db, _backgroundWorker, pEvtArg, _inventoryCommandRequest);
  						break;
  					case InventoryCommand.Activate:
  					case InventoryCommand.Deactivate:
  					case InventoryCommand.Archive:
  						executeCommand(_db, _backgroundWorker, pEvtArg, _inventoryCommandRequest);
  						break;
  					case InventoryCommand.Export:
  						executeExport(_db, _backgroundWorker, pEvtArg, _inventoryCommandRequest);
  						break;
  					default:
  						throw new ArgumentException("Unexpected InventoryCommand [" + _inventoryCommandRequest.InventoryCommand + "]");
  				}
  
  				if (pEvtArg.Cancel) {
  					pEvtArg.Result = new InventoryCommandResponse(_inventoryCommandRequest, false);
  					return;
  				}
  
  				_db.CommitTransaction();
  				pEvtArg.Result = new InventoryCommandResponse(_inventoryCommandRequest, true);
  				_backgroundWorker.ReportStatus("Finished Batch Command: [" + _inventoryCommandRequest.InventoryCommand + "]");
  			}
  		}
  
  		public static void Activate(int pRetailAcctId, decimal pAmount, List<long> pPhoneNumbers, out long pPIN, out long pSerialNumber) {
  			pPIN = 0;
  			pSerialNumber = 0;
  			using (var _db = new Rbr_Db()) {
  				_db.BeginTransaction();
  
  				//-- get account
  				var _retailAcct = RetailAccountManager.Instance.GetAcct(_db, pRetailAcctId);
  				if (_retailAcct == null) {
  					throw new RbrException(RbrResult.POSA_AcctNotFound, string.Empty);
  				}
  
  				if (_retailAcct.Status != Status.Active) {
  					_retailAcct.Status = Status.Active;
  					RetailAccountManager.Instance.UpdateAcct(_db, _retailAcct);
  				}
  				_db.CommitTransaction();
  			}
  		}
  
  		public static void Recharge(int pRetailAcctId, decimal pAmount) {
  			using (var _db = new Rbr_Db()) {
  				_db.BeginTransaction();
  
  				//-- get account
  				var _retailAcct = RetailAccountManager.Instance.GetAcct(_db, pRetailAcctId);
  				if (_retailAcct == null) {
  					throw new RbrException(RbrResult.POSA_AcctNotFound, string.Empty);
  				}
  
  				if (_retailAcct.Status != Status.Active) {
  					throw new RbrException(RbrResult.POSA_InvalidAcctStatus, string.Empty);
  				}
  
  				_retailAcct.Status = Status.Active;
  				RetailAccountManager.Instance.UpdateAcct(_db, _retailAcct);
  				_db.CommitTransaction();
  			}
  		}
  
  		public static void Deactivate(int pRetailAcctId) {
  			using (var _db = new Rbr_Db()) {
  				_db.BeginTransaction();
  
  				//-- get account
  				var _retailAcct = RetailAccountManager.Instance.GetAcct(_db, pRetailAcctId);
  				if (_retailAcct == null) {
  					throw new RbrException(RbrResult.POSA_AcctNotFound, string.Empty);
  				}
  
  				if (_retailAcct.Status == Status.Active) {
  					_retailAcct.Status = Status.Blocked;
  					RetailAccountManager.Instance.UpdateAcct(_db, _retailAcct);
  				}
  
  				_db.CommitTransaction();
  			}
  		}
  
  		public static RetailAccountRow CreateRetailAccount(InventoryCommandRequest pInventoryCommandRequest) {
  			using (var _db = new Rbr_Db()) {
  
gt: 				return createRetailAccount(_db, pInventoryCommandRequest);