/*******************************************************************************
 *  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.segments.MSH;
import cdac.medinfo.sdk.hl7282.commoninterface.ISegment;
import cdac.medinfo.sdk.hl7282.commoninterface.ISegmentSet;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidMessageException;
import cdac.medinfo.sdk.hl7282.exceptions.MessageNotSupportedException;
import cdac.medinfo.sdk.hl7282.utils.EnumMessageCode;
import cdac.medinfo.sdk.hl7282.utils.EnumSegments;
import cdac.medinfo.sdk.hl7282.utils.EnumTriggerEvent;
import cdac.medinfo.sdk.hl7282.utils.StandardMethods;

/**
 * Message_Source_Recepient class is the abstract class which Declares the Methods verify, canSend, canReceive.
 * This class verifies Message according to MessageCode and TriggerEvent.
 * It also checks weather User is capable to Send and Receive the Message.
 */
public abstract class Message_Source_Recepient 
{
	

	protected IMessageFactory objMessageFactory = null;

	public Message_Source_Recepient(IMessageFactory objMessageFactory)
	{
		this.objMessageFactory = objMessageFactory; 
	}

	/**
	 * Checks whether underlying Message Recipient can send specified Message or not.
	 * @param enumMessageCode specified message code
	 * @param enumTriggerEvent specified trigger event
	 * @return boolean status as true or false
	 */
	public abstract boolean canSend(EnumMessageCode enumMessageCode,EnumTriggerEvent enumTriggerEvent);

	/**
	 * Checks whether underlying Message Recipient can receive specified Message or not.
	 * @param enumMessageCode specified message code
	 * @param enumTriggerEvent specified trigger event
	 * @return boolean status as true or false
	 */
	public abstract boolean canReceive(EnumMessageCode enumMessageCode,EnumTriggerEvent enumTriggerEvent);

	/**
	 * Creates Empty Message with Message Structure & Trigger Event specified.
	 * @param enumMessageCode specified message code.
	 * @param enumTriggerEvent specified trigger event
	 * @return Message - Generated Empty Message
	 * @throws MessageNotSupportedException Thrown when Message creation is not supported by HL7 SDK
	 */
	public Message createMessage(EnumMessageCode enumMessageCode,EnumTriggerEvent enumTriggerEvent) throws MessageNotSupportedException
	{
		Message objMessage = null;

		if(canSend(enumMessageCode,enumTriggerEvent))
		{
			objMessage = objMessageFactory.createMessage(enumMessageCode,enumTriggerEvent);
		}
		else
			throw new MessageNotSupportedException(enumTriggerEvent.getValue());
		return objMessage;
	}

	/**
	 * Populates Message from HL7 Stream.  
	 * @param objISegmentSet instance of SegmentSet
	 * @return Message instance of populated message
	 * @throws MessageNotSupportedException Thrown when Message creation is not supported by HL7 SDK
	 * @throws InvalidMessageException if Message validation fails
	 */
	public Message populateMessage(ISegmentSet objISegmentSet) throws MessageNotSupportedException,InvalidMessageException
	{
		ISegment objTempSegment = objISegmentSet.getSegment(0);
		EnumTriggerEvent enumTriggerEvent = null;
		EnumMessageCode enumMessageCode = null;
		if(objTempSegment.getName().equals(EnumSegments.HL7_SEG_MSH))
		{
			MSH objMSH = (MSH)objTempSegment;
			enumTriggerEvent =  StandardMethods.getEnumTriggerEvent((String)objMSH.getMessageType().getTriggerEvent().getValue());
			enumMessageCode = StandardMethods.getEnumMessageCode((String)objMSH.getMessageType().getMessageCode().getValue());
		}

		return (populateMessage(enumMessageCode, enumTriggerEvent, objISegmentSet));
	}

	/**
	 * Populates Message with Specified Message Structure & Message Trigger Event from SegmentSet.  
	 * @param enumMessageCode specified message code
	 * @param enumTriggerEvent specified trigger event
	 * @param objISegmentSet instance of SegmentSet
	 * @return Message instance of populated message
	 * @throws MessageNotSupportedException Thrown when Message creation is not supported by HL7 SDK
	 * @throws InvalidMessageException if Message validation fails
	 */
	public Message populateMessage(EnumMessageCode enumMessageCode,EnumTriggerEvent enumTriggerEvent, ISegmentSet objISegmentSet) throws MessageNotSupportedException,InvalidMessageException
	{
		Message objMessage = null;

		if(canReceive(enumMessageCode,enumTriggerEvent))
		{
			objMessage = objMessageFactory.createMessage(enumMessageCode,enumTriggerEvent);
			objMessage.populate(objISegmentSet);
		}
		else
			throw new MessageNotSupportedException(enumTriggerEvent.getValue());
		return objMessage;
	}
}
