package cdac.medinfo.sdk.hl7282.hl7net.auxiliaryprotocol.querycancel;

import java.util.Locale;

import cdac.medinfo.sdk.hl7282.baselibs.segments.MSA;
import cdac.medinfo.sdk.hl7282.baselibs.segments.MSH;
import cdac.medinfo.sdk.hl7282.baselibs.segments.QID;
import cdac.medinfo.sdk.hl7282.baselibs.segments.QPD;
import cdac.medinfo.sdk.hl7282.commoninterface.ISegment;
import cdac.medinfo.sdk.hl7282.commoninterface.ISegmentSet;
import cdac.medinfo.sdk.hl7282.commoninterface.ISingleCollection;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidMessageException;
import cdac.medinfo.sdk.hl7282.hl7net.commons.IServerQueryCancellation;
import cdac.medinfo.sdk.hl7282.utils.EnumMessageCode;
import cdac.medinfo.sdk.hl7282.utils.EnumSegments;
import cdac.medinfo.sdk.hl7282.utils.HL7Config;
import cdac.medinfo.sdk.hl7282.utils.HL7Logger;
import cdac.medinfo.sdk.hl7282.utils.IPairedCollection;
import cdac.medinfo.sdk.hl7282.utils.PairedCollection;
import cdac.medinfo.sdk.hl7282.utils.ResourceBundleWrapper;
import cdac.medinfo.sdk.hl7282.utils.SingleCollection;

/**
 * This class provides the Cancellation Message against the Query Message, if user has set the Agent.
 */
public class ServerSideQCNAgent implements IServerQueryCancellation
{
	
	/**Collection of query id for all queries.*/
	ISingleCollection<String> objClientQueryIDCollection = null;

	/**Collection of query id for which cancellation query is triggered.*/
	ISingleCollection<String> objCancelledQueryIDCollection = null;

	/**Collection of Canceled Messages stored. */
	ISingleCollection<ISegmentSet> objStoredCancelledessages =null;

	/**Collection of QueryId and MessageControlID */
	IPairedCollection<String,String> objQueryMctrlIDCollection =null;

	public ServerSideQCNAgent()
	{
		objClientQueryIDCollection = new SingleCollection<String> ();
		objCancelledQueryIDCollection = new SingleCollection<String> ();
		objStoredCancelledessages = new SingleCollection<ISegmentSet> ();
		objQueryMctrlIDCollection = new PairedCollection<String, String>();
	}
	
	/**
	 * This method will return the collection of Strings.
	 * @return ISingleCollection<String> Collection of query id which are canceled.
	 */
	public ISingleCollection<String> getCancelledResponses() 
	{
		ISingleCollection<String> objQueryIDCollection = null;
		for(String strQueryid : objCancelledQueryIDCollection)
		{
			if(objQueryIDCollection==null)
				objQueryIDCollection = new SingleCollection<String>(); 
			objQueryIDCollection.add(strQueryid);
		}
		return objQueryIDCollection;
	}
	
	/**
	 * This method keeps track for the queries which are send by Sever.
	 * @param objSegmentSet Object of Segment Set which send by Server.
	 * @return boolean - This will return true if received segment set is invalid or canceled.
	 */
	public boolean processSend(ISegmentSet objSegmentSet) 
	{
		String strMessageControlID = null; 
		ISingleCollection<ISegment> objSegmentCollection = objSegmentSet.getList();
		if(objSegmentCollection!= null && objSegmentCollection.size()>0)
		{
			int iSegSetSize = objSegmentCollection.size();
			boolean isMessageHeaderSet = false;
			for(int iRead=0;iRead<iSegSetSize;iRead++)
			{
				ISegment objSegment = null;
				objSegment = objSegmentCollection.elementAt(iRead);
				if(objSegment == null)
					throw new InvalidMessageException(this.getClass().getSimpleName());
				EnumSegments enumSegments = (EnumSegments) objSegment.getName();
				switch(enumSegments)
				{
				case HL7_SEG_MSH:
					if(false == isMessageHeaderSet)
						isMessageHeaderSet = true;
					else
						throw new InvalidMessageException(this.getClass().getSimpleName());
					break;
				case HL7_SEG_MSA:
					MSA objMSASegment = (MSA)objSegment;
					strMessageControlID =(String)objMSASegment.getMessageControlID().getValue();
					break;
				}
			}
			//This method will return true in case of Exceptional scenarios and in Message Agent
			//exception will be thrown.
			//Client Receives response and verify it is canceled then add that in collection 
			//if it is set by user else remove.
			String strQueryIdentifier = objQueryMctrlIDCollection.get(strMessageControlID);
			if(objCancelledQueryIDCollection.contains(strQueryIdentifier))
			{
				objClientQueryIDCollection.remove(strQueryIdentifier);

				//Status logging
				if(HL7Config.createInstance().isLoggingOn())
				{
					String strSendingMessage = ResourceBundleWrapper.getValue("exceptions", "QCN_SendingMessage",new Locale(HL7Config.createInstance().getLocale())) + strQueryIdentifier;
					HL7Logger objHLogger = HL7Logger.getLogger();
					objHLogger.log(strSendingMessage);
				}
				
				throw new InvalidMessageException(ResourceBundleWrapper.getValue("exceptions", "QC_CancelledResponse",new Locale(HL7Config.createInstance().getLocale())));
			}
			else
			{
				objClientQueryIDCollection.remove(strQueryIdentifier);

				//Status logging
				if(HL7Config.createInstance().isLoggingOn())
				{
					String strSendingMessage = ResourceBundleWrapper.getValue("exceptions", "QCN_SendingMessage",new Locale(HL7Config.createInstance().getLocale())) + strQueryIdentifier;
					HL7Logger objHLogger = HL7Logger.getLogger();
					objHLogger.log(strSendingMessage);
				}
			}
		}
		return false;
	}
	
	/**
	 * This method will keep track for all responses which are received at Server Side.
	 * @return boolean - true if received Segment Set is for cancellation else false.   
	 */
	public boolean processReceive(ISegmentSet objSegmentSet) 
	{
		try
		{
			MSH objMSHSegment = null;
			String strQueryID = null; 
			ISingleCollection<ISegment> objSegmentCollection = objSegmentSet.getList();
			if(objSegmentCollection!= null && objSegmentCollection.size()>0)
			{
				int iSegSetSize = objSegmentCollection.size();
				boolean isMessageHeaderSet = false;
				for(int iRead=0;iRead<iSegSetSize;iRead++)
				{
					ISegment objSegment = null;
					objSegment = objSegmentCollection.elementAt(iRead);
					if(objSegment == null)
						throw new InvalidMessageException(this.getClass().getSimpleName());
					EnumSegments enumSegments = (EnumSegments) objSegment.getName();
					switch(enumSegments)
					{
					case HL7_SEG_MSH:
						if(false == isMessageHeaderSet)
						{
							objMSHSegment = (MSH)objSegment;
							isMessageHeaderSet = true;
						}
						else
							throw new InvalidMessageException(this.getClass().getSimpleName());
						break;
					case HL7_SEG_QPD:
						QPD objQPDSegment= (QPD)objSegment;
						strQueryID =(String)objQPDSegment.getQueryTag().getValue();
						break;
					case HL7_SEG_QID:
						QID objQIDSegment = (QID)objSegment;
						strQueryID =(String)objQIDSegment.getQueryTag().getValue();
						break;
					}
				}
			}
			// If while sending query from client if entry is not done then add.
			if(objMSHSegment!=null && objMSHSegment.getMessageType().getMessageCode().getValue().equals(EnumMessageCode.QCN.getValue()))
			{
				if(objClientQueryIDCollection.size() > 0)
				{
					if(objClientQueryIDCollection.contains(strQueryID))
					{
						//Add entry in collection of canceled query id's and remove it from the collection of Query id.
						//checking of repetitive query id will not be part of QCN agent. 
						objCancelledQueryIDCollection.add(strQueryID);
						objClientQueryIDCollection.remove(strQueryID);

						String strQueryCancelled = ResourceBundleWrapper.getValue("exceptions", "QC_QueryCancelled",new Locale(HL7Config.createInstance().getLocale()))+strQueryID;
						if(HL7Config.createInstance().isLoggingOn())
						{
							HL7Logger objhl7Logger = HL7Logger.getLogger();
							objhl7Logger.log(strQueryCancelled);
						}
					}
					else if(HL7Config.createInstance().isLoggingOn())
					{
						String strQueryCancelled = ResourceBundleWrapper.getValue("exceptions", "QC_NOQuery",new Locale(HL7Config.createInstance().getLocale()))+strQueryID;

						HL7Logger objhl7Logger = HL7Logger.getLogger();
						objhl7Logger.log(strQueryCancelled);
					}
				}
				else if(HL7Config.createInstance().isLoggingOn())
				{
					String strQueryCancelled = ResourceBundleWrapper.getValue("exceptions", "QC_InvalidQueryCancel",new Locale(HL7Config.createInstance().getLocale()))+strQueryID;

					HL7Logger objhl7Logger = HL7Logger.getLogger();
					objhl7Logger.log(strQueryCancelled);
				}

				//Status logging
				if(HL7Config.createInstance().isLoggingOn())
				{
					String strSendingMessage = ResourceBundleWrapper.getValue("exceptions", "QCN_RecievedMessage",new Locale(HL7Config.createInstance().getLocale())) + strQueryID;
					HL7Logger objHLogger = HL7Logger.getLogger();
					objHLogger.log(strSendingMessage);
				}
				return true;
			}//This will add query id for those query which are triggered no repetitive query id is inserted. 
			else 
			{
				if(!objClientQueryIDCollection.contains(strQueryID))
					objClientQueryIDCollection.add(strQueryID);
				objQueryMctrlIDCollection.put((String)objMSHSegment.getMessageControlID().getValue(),strQueryID);

				//Status logging
				if(HL7Config.createInstance().isLoggingOn())
				{
					String strSendingMessage = ResourceBundleWrapper.getValue("exceptions", "QCN_RecievedMessage",new Locale(HL7Config.createInstance().getLocale())) + strQueryID;
					HL7Logger objHLogger = HL7Logger.getLogger();
					objHLogger.log(strSendingMessage);
				}
			}
			return false;
		}
		catch(InvalidMessageException ime)
		{
			if(HL7Config.createInstance().isLoggingOn())
			{
				HL7Logger objHLogger = HL7Logger.getLogger();
				objHLogger.log(ime);
			}
			throw ime;	
		}
	}
}
