/*******************************************************************************
 *  Copyright 2017 Centre for Development of Advanced Computing(C-DAC), Pune
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  
 *    http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *******************************************************************************/
package cdac.medinfo.sdk.hl7282.baselibs.messages;


import cdac.medinfo.sdk.hl7282.baselibs.ST;
import cdac.medinfo.sdk.hl7282.baselibs.segments.DSC;
import cdac.medinfo.sdk.hl7282.baselibs.segments.MSA;
import cdac.medinfo.sdk.hl7282.baselibs.segments.QID;
import cdac.medinfo.sdk.hl7282.baselibs.segments.QPD;
import cdac.medinfo.sdk.hl7282.baselibs.segments.RCP;
import cdac.medinfo.sdk.hl7282.baselibs.segments.Segment;
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.utils.EnumSegments;
import cdac.medinfo.sdk.hl7282.utils.IMap;
import cdac.medinfo.sdk.hl7282.utils.SingleCollection;

/**
 *  Message is Parent Class of All Query messages in HL7Standard. 
 */
public abstract class AbstractQuery extends Message    
{


	

	//Sets Query which is Interactive.  
	boolean isInteractiveQuery = false;

	//Sets Response which is Interactive.  
	boolean isInteractiveResponse = false;

	//Sets Query which is Canceled.  
	boolean isCanceledQuery = false;

	//Sets Response which is Canceled.  
	boolean isCanceledResponse = false;

	/**
	 * Checks whether expected response for query is batch or single response.
	 * @return boolean 
	 */
	public boolean isBatchRSPExpected()
	{
		if(contains(EnumSegments.HL7_SEG_RCP))
		{
			ISingleCollection<ISegment> objRCPCollection = getSegment(EnumSegments.HL7_SEG_RCP);
			if(objRCPCollection!=null)
			{
				RCP objRCP = (RCP)objRCPCollection.elementAt(0);
				if(objRCP.getResponseModality()!=null)
				{
					if(objRCP.getResponseModality().equals("B"))
						return true;					
				}
			}
		}
		return false;
	}

	/**
	 * Retrieves Query Identifier depending upon Original or Deferred mode 
	 * @return boolean 
	 */
	public ST getQueryIdentifier()
	{
		if(contains(EnumSegments.HL7_SEG_QPD))
		{
			ISingleCollection<ISegment> objQPDCollection  = getSegment(EnumSegments.HL7_SEG_QPD);
			if(objQPDCollection!=null)
			{
				QPD objQPD = (QPD)objQPDCollection.elementAt(0);
				return objQPD.getQueryTag();
			}	
		}
		if(contains(EnumSegments.HL7_SEG_QID))
		{
			ISingleCollection<ISegment> objQIDCollection = getSegment(EnumSegments.HL7_SEG_QID);
			if(objQIDCollection!=null)
			{
				QID objQID =(QID)objQIDCollection.elementAt(0);
				return objQID.getQueryTag();				
			}
		}
		if(contains(EnumSegments.HL7_GROUP_QUERY_INFORMATION) || contains(EnumSegments.HL7_GROUP_QUERY_ACK_IPR) || contains(EnumSegments.HL7_GROUP_QUERY) || contains(EnumSegments.HL7_GROUP_QUERY_ACK))
		{
			ISegmentSet objSegmentSet = getSegmentSet();
			int i = 1;
			ISegment objSegment = null;
			while(i<= objSegmentSet.size())
			{
				objSegment = objSegmentSet.getSegment(i);
				
				if(objSegment.getName() == EnumSegments.HL7_SEG_QPD)
				{
					QPD objQPD = (QPD)objSegment;
					return objQPD.getQueryTag();
				}
				
				i++;
			}
			
		}
		return null;
	}

	/**
	 * Checks whether Query Priority is Deferred or Immediate
	 * @return boolean 
	 */
	public boolean isDeferred()
	{
		if(contains(EnumSegments.HL7_SEG_RCP))
		{
			ISingleCollection<ISegment> objRCPCollection  =  getSegment(EnumSegments.HL7_SEG_RCP);

			if(objRCPCollection!=null)
			{
				RCP objRCP = (RCP)objRCPCollection.elementAt(0);
				if(objRCP.getQuantityLimitedRequest()!=null)
				{
					if("D".equals(objRCP.getQueryPriority().getValue()))
						return true;
				}
			}
		}
		return false;
	}

	/**
	 * Gives the Segments used to Query.
	 * @return ISingleCollection<Segment> - collection of segments used query.
	 */
	public ISingleCollection<Segment> getQuerySegments()
	{
		ISingleCollection<Segment> objQuerySegmentCollection = new SingleCollection<Segment>();
		if(contains(EnumSegments.HL7_SEG_QPD))
		{
			ISingleCollection<ISegment> objQPDCollection = getSegment(EnumSegments.HL7_SEG_QPD);
			if(objQPDCollection!=null)
			{
				QPD objQPD = (QPD)objQPDCollection.elementAt(0);
				objQuerySegmentCollection.add(objQPD);
			}
			if(contains(EnumSegments.HL7_SEG_RCP))
			{
				ISingleCollection<ISegment> objRCPCollection =getSegment(EnumSegments.HL7_SEG_RCP);
				if(objRCPCollection!=null)
				{
					RCP objRCP = (RCP)objRCPCollection.elementAt(0);
					objQuerySegmentCollection.add(objRCP);
				}
			}
			if(contains(EnumSegments.HL7_SEG_DSC))
			{
				ISingleCollection<ISegment> objRCPCollection =getSegment(EnumSegments.HL7_SEG_DSC);
				if(objRCPCollection!=null)
				{
					DSC objDSC = (DSC)objRCPCollection.elementAt(0);
					objQuerySegmentCollection.add(objDSC);
				}
			}
			if (contains(EnumSegments.HL7_SEG_MSA))
			{
				ISingleCollection<ISegment> objRCPCollection =getSegment(EnumSegments.HL7_SEG_MSA);
				if(objRCPCollection!=null)
				{
					MSA objMSA = (MSA)objRCPCollection.elementAt(0);
					objQuerySegmentCollection.add(objMSA);
				}
			}
		}

		if(objQuerySegmentCollection.size()==0)
			return null;
		else 
			return objQuerySegmentCollection;
	}
	
	/**
	 * Parameterized Constructor of Abstract Query which takes MessageMap, Message Code, Trigger Event and Message Structure.
	 * @param objMessageMap Object of IMap.
	 * @param strMessageCode Message Code of Message
	 * @param strTriggerEvent Event of Message
	 * @param strMessageStructure Message structure of Message
	 */
	public AbstractQuery(IMap objMessageMap, String strMessageCode, String strTriggerEvent, String strMessageStructure)
	{
		super(objMessageMap, strMessageCode, strTriggerEvent, strMessageStructure);
	}
	
	/**
	 * Verifies whether Query is Interactive.
	 * @param isInteractive it will set whether query is interactive. 
	 */
	public void setIsInteractiveQuery(boolean isInteractive)
	{
		this.isInteractiveQuery =  isInteractive;
	}
	/**
	 * Returns the status for query whether it is interactive or not. 
	 * @return boolean true if query is interactive else false
	 */
	public boolean isInteractiveQuery()
	{
		return isInteractiveQuery;
	}
	/**
	 * Verifies whether Response is Interactive.
	 * @param isInteractive it will set whether Response is interactive. 
	 */
	public void setIsInteractiveResponse(boolean isInteractiveResponse)
	{
		this.isInteractiveResponse =  isInteractiveResponse;
	}
	/**
	 * Returns the status for Response whether it is interactive or not. 
	 * @return boolean true if Response is interactive else false
	 */
	public boolean isInteractiveResponse()
	{
		return isInteractiveResponse;
	}
	/**
	 * Verifies whether Query is canceled.
	 * @param isCanceledQuery it will set whether query is canceled. 
	 */
	public void setIsCanceledQuery(boolean isCanceledQuery)
	{
		this.isCanceledQuery =  isCanceledQuery;
	}
	/**
	 * Returns the status for query whether it is Canceled or not. 
	 * @return boolean true if query is Canceled else false
	 */
	public boolean isCanceledQuery()
	{
		return isCanceledQuery;
	}
	/**
	 * Verifies whether Response is Canceled.
	 * @param isCanceledResponse it will set whether Response is Canceled. 
	 */
	public void setIsCanceledResponse(boolean isCanceledResponse)
	{
		this.isCanceledResponse =  isCanceledResponse;
	}
	/**
	 * Returns the status for Response whether it is Canceled or not. 
	 * @return boolean true if Response is Canceled else false
	 */
	public boolean isCanceledResponse()
	{
		return isCanceledResponse;
	}
}
