using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Xml.Serialization ;
using Microsoft.RFIDLab.EPCISDemo.Common ;
using Microsoft.RFIDLab.EPCISDemo.EPCEvent ;
using Microsoft.RFIDLab.EPCISDemo.ReceiverWS.Pip3B2 ;

namespace Microsoft.RFIDLab.EPCISDemo.ReceiverWS
{
	/// <summary>
	/// Web-service to perform recevier related operations.
	/// </summary>
	[WebService(Namespace="http://www.microsoft.com/RFIDLab/TrackAndTraceDemo")]
	public class ReceiverWebService : System.Web.Services.WebService
	{
		private TrackTraceDBManager dbManager ; // the data-base manager

		/// <summary>
		/// Default constructor.
		/// </summary>
		public ReceiverWebService ()
		{
			//CODEGEN: This call is required by the ASP.NET Web Services Designer
			InitializeComponent();

			dbManager = new TrackTraceDBManager (
				TrackTraceDBManager.Constants.Receiver ) ;

		} // end of constructor ()

		#region Component Designer generated code
		
		//Required by the Web Services Designer 
		private IContainer components = null;
				
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if(disposing && components != null)
			{
				components.Dispose();
			}
			base.Dispose(disposing);		
		}
		
		#endregion

		/// <summary>
		/// Receives and processes a business-request.
		/// </summary>
		/// <param name="objBusinessRequest">Business-request object. </param>
		/// <returns>Business-response object. </returns>
		[System.Web.Services.WebMethod()]			
		public BusinessResponse ReceiveBusinessRequest (
			BusinessRequest objBusinessRequest )
		{
			// create a new business-response object
			BusinessResponse objBusinessResponse = new BusinessResponse () ;
			
			// if the process-indicator is 3B2, populate the business-response
			if ( objBusinessRequest.GlobalProcessIndicatorCode.ToUpper () ==
				"3B2" )
			{
				// set the process-indicator code
				objBusinessResponse.GlobalProcessIndicatorCode =
					objBusinessRequest.GlobalProcessIndicatorCode ;

				// create the acknowledgement for the business-response
				ReceiptAcknowledgement acknowledgement =
					new ReceiptAcknowledgement () ;	
			
				Pip3B2.Pip3B2AdvanceShipmentNotification asn =
					( Pip3B2.Pip3B2AdvanceShipmentNotification )
					objBusinessRequest.objPip ; // get the PIP object

				//Create and Log EPC Business Event indicating Receipt of ASN from
				//Manufacturer.
				LogEPCStatus ( asn,
					TrackTraceDBManager.Constants.AsnFromManufacturerToReceiver) ;

				// populate the acknowledgement
				acknowledgement.fromRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.lang =
					asn.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.lang ;
				acknowledgement.fromRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value =
					asn.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value ;
				acknowledgement.fromRole.PartnerRoleDescription.ContactInformation.EmailAddress =
					asn.toRole.PartnerRoleDescription.ContactInformation.EmailAddress ;
				acknowledgement.fromRole.PartnerRoleDescription.ContactInformation.facsimileNumber.CommunicationsNumber =
					asn.toRole.PartnerRoleDescription.ContactInformation.facsimileNumber.CommunicationsNumber ;
				acknowledgement.fromRole.PartnerRoleDescription.ContactInformation.telephoneNumber.CommunicationsNumber =
					asn.toRole.PartnerRoleDescription.ContactInformation.telephoneNumber.CommunicationsNumber ;
				acknowledgement.fromRole.PartnerRoleDescription.GlobalPartnerRoleClassificationCode =
					asn.toRole.PartnerRoleDescription.GlobalPartnerRoleClassificationCode ;
				acknowledgement.receivedDocumentDateTime.DateTimeStamp =
					DateTime.UtcNow.ToUniversalTime ().ToString ( "yyyyMMddThhmmss.000Z" ); ;
				acknowledgement.receivedDocumentIdentifier.ProprietaryDocumentIdentifier =
					asn.thisDocumentIdentifier.ProprietaryDocumentIdentifier ;
				acknowledgement.thisMessageDateTime.DateTimeStamp =
					DateTime.UtcNow.ToUniversalTime ().ToString ( "yyyyMMddThhmmss.000Z" ); ;
				acknowledgement.thisMessageIdentifier.ProprietaryMessageIdentifier =
					"Acknowledgement from Receiver. " ;
				acknowledgement.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.lang =
					asn.fromRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.lang ;
				acknowledgement.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value =
					asn.fromRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value ;
				acknowledgement.toRole.PartnerRoleDescription.ContactInformation.EmailAddress =
					asn.fromRole.PartnerRoleDescription.ContactInformation.EmailAddress ;
				acknowledgement.toRole.PartnerRoleDescription.ContactInformation.facsimileNumber.CommunicationsNumber =
					asn.fromRole.PartnerRoleDescription.ContactInformation.facsimileNumber.CommunicationsNumber ;
				acknowledgement.toRole.PartnerRoleDescription.ContactInformation.telephoneNumber.CommunicationsNumber =
					asn.fromRole.PartnerRoleDescription.ContactInformation.telephoneNumber.CommunicationsNumber ;
				acknowledgement.toRole.PartnerRoleDescription.GlobalPartnerRoleClassificationCode =
					asn.fromRole.PartnerRoleDescription.GlobalPartnerRoleClassificationCode ;
				objBusinessResponse.objAcknowledgement =
					acknowledgement ;
				objBusinessResponse.objPip = asn ; // set the PIP object
				// set the acknowledgement
				objBusinessResponse.objAcknowledgement = acknowledgement ;
				// log the event to the data-base

				LogEPCStatus ( asn,
					TrackTraceDBManager.Constants.AcknowledgementFromReceiverToManufacturer ) ;

			} // end if
			
			return objBusinessResponse ; // return the business-response

		} // end of ReceiveBusinessRequest ()

		/// <summary>
		/// Receives and processes a business-acknowledgement.
		/// </summary>
		/// <param name="objReceiptAcknowledgement">Business-acknowledgement.
		/// </param>
		/// <returns>True or false, depending upon the acknowledgement.
		/// </returns>
		[System.Web.Services.WebMethod()]			
		public  bool ReceiveBusinessAcknowledgement (
			ReceiptAcknowledgement objReceiptAcknowledgement )
		{
			//As part of the scope of the current project, we DO NOT need to store the acknowledgement 
			//that we receive - to the database.
			//So this method will just make sure that the Acknowledgement is not null, and return a true
			//or a false
			if ( objReceiptAcknowledgement != null )
				return true ; // end if
			else
				return false ; // end else

		} // end of ReceiveBusinessAcknowledgement ()

		/// <summary>
		/// Adds event-status into the receiver's data-base.
		/// </summary>
		/// <param name="epcTags">EPC tag-IDs. </param>
		/// <param name="eventType">The event-type. </param>
		/// <param name="dateTime">The date-time when the event occured.
		/// </param>
		public void AddEpcEvent ( ArrayList epcTags, int eventType,
			DateTime dateTime )
		{
			// make an instance of the track-trace DB manager
			TrackTraceDBManager manager = new TrackTraceDBManager (
				TrackTraceDBManager.Constants.Receiver ) ;

			// for each EPC-tag, add the EPC-status info to the data-base
			manager.AddEpcStatusInfo ( epcTags.ToArray (), eventType, dateTime ) ;

		} // end of AddEpcEvent ()


		/// <summary>
		/// Receives EPC events.
		/// Log the event to local database and call ReceivingAgent web service
		/// to forward the event.
		/// </summary>summary>
		/// <param name="objEPCEvent">Encapsulated EPC information. </param>
		/// 
		[WebMethod ()]
		public void ReceiveEPCEvent (
			EPCEvent.EquipmentProductCodeInformation objEPCEvent )
		{			
			// create a new Equipment product-code information object
			EPCEvent.EquipmentProductCodeInformation obj =
				new EquipmentProductCodeInformation () ;
			/* create a new equipment product-code information object for the
			 * receiving-agent web-service */
			
			ReceivingAgentWS.EquipmentProductCodeInformation temp =
				new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.EquipmentProductCodeInformation () ;

			if ( objEPCEvent != null ) // if the EPC event object is not null
			{
				// get the order-number
				string ordernumber = objEPCEvent.BusinessTransactionIdentifier ;
				// set the order-number
				temp.BusinessTransactionIdentifier = ordernumber ;
				temp.EquipmentProductCodeEvent =
					new ReceivingAgentWS.EquipmentProductCodeEvent[objEPCEvent.EquipmentProductCodeEventCollection.Count] ;
				string epctag ;
				int eventid ;
				System.DateTime datetime ;
				int i = 0 ;
				temp.CurrentAgent= new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.CurrentAgent () ;
				temp.CurrentAgent.Agent = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.Agent () ;
				temp.CurrentAgent.Agent.reportedBy = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.reportedBy () ;
				temp.CurrentAgent.Agent.reportedBy.PartnerDescription = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.PartnerDescription2 () ;
				temp.CurrentAgent.Agent.reportedBy.PartnerDescription.ContactInformation = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.ContactInformation2 () ;
				temp.CurrentAgent.Agent.reportedBy.PartnerDescription.ContactInformation.contactName = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.contactName2 () ;
				temp.CurrentAgent.Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.FreeFormText2 () ;
				temp.CurrentAgent.Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText.Value =
					objEPCEvent.CurrentAgent.Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText.Value ;

				// for each pallet
				foreach ( EPCEvent.EquipmentProductCodeEvent objPallet in
					objEPCEvent.EquipmentProductCodeEventCollection )
				{
					// get the EPC tag
					epctag = objPallet.EquipmentProductCode.FreeFormText.Value ;

					eventid = Convert.ToInt32 ( objPallet.EPCEventIdentifier ) ;
					datetime = System.DateTime.Now ;
					temp.EquipmentProductCodeEvent[i] =
						new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.EquipmentProductCodeEvent () ;
					temp.EquipmentProductCodeEvent[i].EventType = objPallet.EventType ;
					temp.EquipmentProductCodeEvent[i].EPCEventIdentifier = objPallet.EPCEventIdentifier ;
					temp.EquipmentProductCodeEvent[i].EventLocation = new ReceivingAgentWS.EventLocation () ;
					temp.EquipmentProductCodeEvent[i].EventLocation.GlobalLocationIdentifier = objPallet.EventLocation.GlobalLocationIdentifier ;
					temp.EquipmentProductCodeEvent[i].EquipmentProductCode = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.EquipmentProductCode () ;
					temp.EquipmentProductCodeEvent[i].AssociateEquipmentProductCode = new ReceivingAgentWS.AssociateEquipmentProductCode[objPallet.AssociateEquipmentProductCodeCollection.Count] ;
					temp.EquipmentProductCodeEvent[i].EquipmentProductCode.FreeFormText = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.FreeFormText2 () ;
					temp.EquipmentProductCodeEvent[i].EquipmentProductCode.FreeFormText.Value = objPallet.EquipmentProductCode.FreeFormText.Value ;
					temp.EquipmentProductCodeEvent[i].Agent = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.Agent () ;
					temp.EquipmentProductCodeEvent[i].Agent.reportedBy = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.reportedBy () ;
					temp.EquipmentProductCodeEvent[i].Agent.reportedBy.PartnerDescription = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.PartnerDescription2 () ;
					temp.EquipmentProductCodeEvent[i].Agent.reportedBy.PartnerDescription.ContactInformation = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.ContactInformation2 () ;
					temp.EquipmentProductCodeEvent[i].Agent.reportedBy.PartnerDescription.ContactInformation.contactName = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.contactName2 () ;
					temp.EquipmentProductCodeEvent[i].Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.FreeFormText2 () ;
					temp.EquipmentProductCodeEvent[i].Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText.Value =
						objPallet.Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText.Value ;

					dbManager.AddFullEpcStatusInfo ( epctag, eventid, datetime,
						objEPCEvent.CurrentAgent.Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText.Value,
						objPallet.Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText.Value,
						objPallet.EventLocation.GlobalLocationIdentifier ) ;

					int j = 0 ;

					// for each case
					foreach ( EPCEvent.AssociateEquipmentProductCode objCase in
						objPallet.AssociateEquipmentProductCodeCollection )
					{
						// get the EPC tag
						epctag = objCase.FreeFormText.Value ;

						dbManager.AddFullEpcStatusInfo ( epctag, eventid, datetime,
							objEPCEvent.CurrentAgent.Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText.Value,
							objPallet.Agent.reportedBy.PartnerDescription.ContactInformation.contactName.FreeFormText.Value,
							objPallet.EventLocation.GlobalLocationIdentifier ) ;

						temp.EquipmentProductCodeEvent[i].AssociateEquipmentProductCode[j] = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.AssociateEquipmentProductCode () ;
						temp.EquipmentProductCodeEvent[i].AssociateEquipmentProductCode[j].FreeFormText = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.FreeFormText2 () ;
						temp.EquipmentProductCodeEvent[i].AssociateEquipmentProductCode[j++].FreeFormText.Value = objCase.FreeFormText.Value ;

					} // end nested for

					i ++ ;

				} // end outer for

				// create an instance of the receiving-agent web-service proxy
				ReceivingAgentWS.ReceivingAgentWebService rProxy = new Microsoft.RFIDLab.EPCISDemo.ReceivingAgentWS.ReceivingAgentWebService();
				rProxy.ReceiveEPCEvent(temp);
				
			} // end if
			
		} // end of ReceiveEPCEvent ()

		/// <summary>
		/// Logs the EPC status to the data-base.
		/// </summary>
		/// <param name="objPip">The PIP object. </param>
		/// <param name="eventType">The event-type. </param>
		private void LogEPCStatus (
			Pip3B2.Pip3B2AdvanceShipmentNotification objPip,
			int eventType )
		{
			if ( objPip == null ) // if the PIP object is not null
				return ; // end if

			// for each shipping container
			foreach ( Pip3B2.ShippingContainer container in
				objPip.AdvancedShipmentNotification.Shipment.ShippingContainerCollection )
			{
				// get the EPC
				string proprietarySerialIdentifier =
					container.shippingContainerIdentifier.ProprietarySerialIdentifier ;
				int index = proprietarySerialIdentifier.IndexOf ( ' ' ) ;
				string epc = null ;

				if ( index >= 0 )
					epc = proprietarySerialIdentifier.Substring ( 0, index ) ;
				// end if

				string fromRole = null;
				string toRole = null;

				if(eventType == TrackTraceDBManager.Constants.AsnFromManufacturerToReceiver)
				{
					fromRole = objPip.fromRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value;
					toRole = objPip.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value;
				}
				else if(eventType == TrackTraceDBManager.Constants.AcknowledgementFromReceiverToManufacturer)
				{
					fromRole = objPip.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value;
					toRole = objPip.fromRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value;
				}

				// Log the event to data-base
				dbManager.AddFullEpcStatusInfo ( epc, eventType, DateTime.Now,
					fromRole, toRole, "Receiver Location");
					
				// for each shipping container item
				foreach ( Pip3B2.ShippingContainerItem item in
					container.ShippingContainerItemCollection )
				{
					// get the proprietary serial-identifier
					proprietarySerialIdentifier =
						item.shippingContainerItemIdentifier.ProprietarySerialIdentifier ;
					index = proprietarySerialIdentifier.IndexOf ( ' ' ) ;
					epc = null ;

					// set the EPC from the serial-identifier
					if ( index >= 0 )
						epc = proprietarySerialIdentifier.Substring ( 0,
							index  ) ; // end if

					else
						epc = proprietarySerialIdentifier ; // end else

					// add the event to the data-base
					dbManager.AddFullEpcStatusInfo ( epc, eventType, DateTime.Now,
						fromRole, toRole, "Receiver Location");
			
				} // end nested for

			} // end for

		} // end of LogEPCEvent ()
	
	} // class definition over

} // end of namespace
