using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using Microsoft.RFIDLab.EPCISDemo.Common;
using Microsoft.RFIDLab.EPCISDemo.PIP3B13;
using Microsoft.RFIDLab.EPCISDemo.PIP4B2;
using Microsoft.RFIDLab.EPCISDemo.EPCEvent;

namespace Microsoft.RFIDLab.EPCISDemo.ManufacturerWS
{
	/// <summary>
	/// Web-service for manufacturer operations.
	/// </summary>		
	[System.Xml.Serialization.XmlInclude(typeof(Pip3B13ShippingOrderConfirmationNotification)),System.Xml.Serialization.XmlInclude(typeof(EquipmentProductCodeInformation)),System.Xml.Serialization.XmlInclude(typeof(Pip4B2ShipmentReceiptNotification)),System.Xml.Serialization.XmlInclude(typeof(ReceiptAcknowledgement)),WebService(Namespace="http://www.microsoft.com/RFIDLab/TrackAndTraceDemo")]
	public class ManufacturerWebService : System.Web.Services.WebService
	{
		//Database Manager reference for EPC Event Logging.
		private TrackTraceDBManager dbManager;
		private static Common.OrderInformation objOrderInfo;
		
		/// <summary>
		/// Default constructor.
		/// </summary>
		public ManufacturerWebService ()
    	{
			//CODEGEN: This call is required by the ASP.NET Web Services Designer
			InitializeComponent();
			//Initialize DatabaseManager for Manufacturer Database.
			dbManager = new TrackTraceDBManager(TrackTraceDBManager.Constants.Manufacturer);
			
		} // 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">The business-request object. </param>
		/// <returns>Business-response object. </returns>
		/*************************************************************************
		 * Currently, in this Demo Application, Manufacturer Web Service is not
		 * receiving any Business Request. Hence, we construct dummy Business
		 * Response object and return.
		 *************************************************************************/
		[System.Web.Services.WebMethod()]			
		public BusinessResponse ReceiveBusinessRequest(BusinessRequest objBusinessRequest)
		{

			BusinessResponse objBusinessResponse = new BusinessResponse();
			ReceiptAcknowledgement objReceiptAcknowledgement = new ReceiptAcknowledgement();
			objBusinessResponse.objAcknowledgement = objReceiptAcknowledgement;
			objBusinessResponse.objPip = null; //no business response type.
			objBusinessResponse.GlobalProcessIndicatorCode = null; // no response type.
			
			return objBusinessResponse;		
				
		} // end of ReceiveBusinessRequest ()

		/// <summary>
		/// Receives and processes a business-response.
		/// </summary>
		/// <param name="objBusinessResponse">The business-response. </param>
		/// <returns>True or false, depending upon the business-response.
		/// </returns>
		/**************************************************************************
		 * The WebInterface is used to accept Business Acknowledgment. currently
		 * Manufacturer WebService handles following PIP's:
		 * 1. PIP3B13NotifyOfShipmentOrderConfirmation from Shipping Agent.
		 * 2. PIP4B2NotifyOfShipmentReceipt from Receiver confirming receipt of 
		 *    ordered goods.
		 ***************************************************************************/
		[System.Web.Services.WebMethod(EnableSession=true)]			
		public  bool ReceiveBusinessAcknowledgement(BusinessResponse objBusinessResponse)
		{
			if(objBusinessResponse == null)
				return false;

			//Process PIP3B13 Notification.
			if(objBusinessResponse.GlobalProcessIndicatorCode.Equals("3B13"))
			{
				Pip3B13ShippingOrderConfirmationNotification objPIP3B13 = new Pip3B13ShippingOrderConfirmationNotification();

				//Update Database with received Business Information for the EPCs
				Pip3B13ShippingOrderConfirmationNotification objPip3B13 = (Pip3B13ShippingOrderConfirmationNotification)objBusinessResponse.objPip;
				
				objOrderInfo = new Common.OrderInformation();
				objOrderInfo.OrderNumber = objPip3B13.ShipmentConfirmation.OrderInformation.orderNumber.ProprietaryDocumentIdentifier;
				
				Common.PalletItemCollection orderPalletCollection = new Common.PalletItemCollection();

				ShipmentLineItemCollection objShipmentLineItemCollection = objPip3B13.ShipmentConfirmation.ShipmentLineItemCollection;
				for(int i = 0; i < objShipmentLineItemCollection.Count; i++)
				{
					ShipmentLineItem objShipmentLineItem = objShipmentLineItemCollection[i];
					ShippingContainerCollection objPalletArray = objShipmentLineItem.ShippingContainerCollection;
					for(int j = 0; j < objPalletArray.Count; j++)
					{
						ShippingContainer objPallet = objPalletArray[j];
						string strPalletEPC = objPallet.shippingContainerIdentifier.ProprietarySerialIdentifier;
						string strPalletEPCNumber = strPalletEPC.Substring(0, strPalletEPC.IndexOf(" "));

						dbManager.AddFullEpcStatusInfo ( strPalletEPCNumber,
							TrackTraceDBManager.Constants.NotifyOfShippingOrderConfFromShippingAgentToManufacturer,
							System.DateTime.Now, objPip3B13.fromRole.PartnerRoleDescription.PartnerDescription.ContactInformation.contactName.FreeFormText.Value,
							objPip3B13.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value,
							"Manufacturer Location");
							
						Common.PalletItem orderPallet = new Common.PalletItem();
						orderPallet.EpcTagId.FreeFormText.Value = strPalletEPCNumber; //store pallet epc
						Common.CaseItemCollection orderCaseCollection = new Common.CaseItemCollection();

						ShippingContainerItemCollection objCaseArray = objPallet.ShippingContainerItemCollection;
						for(int k = 0; k < objCaseArray.Count; k++)
						{
							ShippingContainerItem objCase = objCaseArray[k];
							string strCaseEPC = objCase.shippingContainerItemIdentifier.ProprietarySerialIdentifier;
							string strCaseEPCNumber = strCaseEPC.Substring(0, strCaseEPC.IndexOf(" "));
							
							dbManager.AddFullEpcStatusInfo ( strCaseEPCNumber,
								TrackTraceDBManager.Constants.NotifyOfShippingOrderConfFromShippingAgentToManufacturer,
								System.DateTime.Now, objPip3B13.fromRole.PartnerRoleDescription.PartnerDescription.ContactInformation.contactName.FreeFormText.Value,
								objPip3B13.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value,
								"Manufacturer Location");
								
							Common.CaseItem orderCase = new Common.CaseItem();
							orderCase.EpcTagId.FreeFormText.Value = strCaseEPCNumber; //store case epc
							orderCaseCollection.Add(orderCase);

						}
						orderPallet.CaseItemCollection = orderCaseCollection;
						orderPalletCollection.Add(orderPallet);
					}

				}

				objOrderInfo.PalletItemCollection = orderPalletCollection;
				Session["OrderInformation"] = objOrderInfo;
				
				return true;

			} //end of processing 3B13 request.
			else if(objBusinessResponse.GlobalProcessIndicatorCode.Equals("4B2"))
			{
				
				Pip4B2ShipmentReceiptNotification objPip4B2 = (Pip4B2ShipmentReceiptNotification)objBusinessResponse.objPip;
				if(objPip4B2.thisDocumentIdentifier.ProprietaryDocumentIdentifier.Equals(objOrderInfo.OrderNumber.ToString()))
				{
					//we found matching order for which we got order receipt confirmation.
					System.DateTime currentTime = System.DateTime.Now;

					foreach(Common.PalletItem pallet in objOrderInfo.PalletItemCollection)
					{
						string palletEPC = pallet.EpcTagId.FreeFormText.Value;

						dbManager.AddFullEpcStatusInfo ( palletEPC,
							TrackTraceDBManager.Constants.NotifyOfShipmentReceiptFromReceiverToManufacturer,
							currentTime, objPip4B2.fromRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value,
							objPip4B2.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value,
							"Manufacturer Location");

                        foreach(Common.CaseItem caseitem in pallet.CaseItemCollection)
						{
							string caseEPC = caseitem.EpcTagId.FreeFormText.Value;

							dbManager.AddFullEpcStatusInfo ( caseEPC,
								TrackTraceDBManager.Constants.NotifyOfShipmentReceiptFromReceiverToManufacturer,
								currentTime, objPip4B2.fromRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value,
								objPip4B2.toRole.PartnerRoleDescription.ContactInformation.contactName.FreeFormText.Value,
								"Manufacturer Location" );

						}
					}
					return true;
				}
				return false; //order number did not match.
			}
			else 
				return false;  //unrecoginzed request type!
		}
		
		/// <summary>
		/// Receives EPC events.
		/// </summary>
		/// <param name="objEPCEvent">Encapsulated EPC-event information.
		/// </param>
		[System.Web.Services.WebMethod()]
		public void ReceiveEPCEvent(EPCEvent.EquipmentProductCodeInformation objEPCEvent)
		{
			
			EPCEvent.EquipmentProductCodeInformation obj = new EquipmentProductCodeInformation();
			if(objEPCEvent != null)
			{
				//Invoke database manager to add the event to database.
				//dbManager.AddEpcStatusInfo (epcTags.ToArray(), eventType, System.DateTime.Now);

				string ordernumber = objEPCEvent.BusinessTransactionIdentifier;
				//In future we can extend the functionality to verify if this ordernumber is
				//of interest to us. It error take appropriate action.

				string epctag;
				int eventid;
				System.DateTime datetime;

				//For now we assume that all communication is valid in demo. loop through
				//pallets and cases and log the epc tag.
				foreach(EPCEvent.EquipmentProductCodeEvent objPallet in objEPCEvent.EquipmentProductCodeEventCollection)
				{
					epctag = objPallet.EquipmentProductCode.FreeFormText.Value;

					eventid = Convert.ToInt32(objPallet.EPCEventIdentifier);
					datetime = System.DateTime.Now;

					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 );

					foreach(EPCEvent.AssociateEquipmentProductCode objCase in objPallet.AssociateEquipmentProductCodeCollection)
					{
						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 );

					}
				}
			}
			
			//done. we do not forward the received EPC event to anyone else.

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

} // end of namespace
