/*******************************************************************************
 *  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.hl7model.messages.patientcare;

import cdac.medinfo.sdk.hl7282.baselibs.messagedictionary.MessageMapReader;
import cdac.medinfo.sdk.hl7282.baselibs.messages.ACK;
import cdac.medinfo.sdk.hl7282.baselibs.messages.IMessageFactory;
import cdac.medinfo.sdk.hl7282.baselibs.messages.Message;
import cdac.medinfo.sdk.hl7282.exceptions.MessageNotSupportedException;
import cdac.medinfo.sdk.hl7282.utils.EnumHL7System;
import cdac.medinfo.sdk.hl7282.utils.EnumMessageCode;
import cdac.medinfo.sdk.hl7282.utils.EnumTriggerEvent;
import cdac.medinfo.sdk.hl7282.utils.IMap;
import cdac.medinfo.sdk.hl7282.utils.IMessageMapReader;

class PatientCareMessageFactory implements IMessageFactory
{
	private static PatientCareMessageFactory objPatientCareMessageFactory = null;
	private static IMessageMapReader objMessamapReader = null;

	private PatientCareMessageFactory()
	{}

	/**
	 * Creates Object of PatientCareMessageFactory.
	 * @return PatientCareMessageFactory object of PatientCareMessageFactory
	 */
	public static PatientCareMessageFactory createInstance()
	{
		if(objPatientCareMessageFactory == null)
		{
			objMessamapReader = MessageMapReader.createInstance(EnumHL7System.HL7_SYSTEM_PATIENTCARE);
			objPatientCareMessageFactory = new PatientCareMessageFactory();
		}
		return objPatientCareMessageFactory;
	}

	/**
	 * Creates Message with specified enumerations of Trigger Event & Message Structure
	 * @param enumMessageCode enumerated value of Message Code
	 * @param enumTriggerEvent enumerated value of Trigger Event
	 * @return Message instance of Message
	 */
	public Message createMessage(EnumMessageCode enumMessageCode,EnumTriggerEvent enumTriggerEvent)
	{
		Message objMessage = null;
		IMap objMessageMap = getMessageMap(enumMessageCode, enumTriggerEvent);

		if(enumMessageCode == EnumMessageCode.ACK)
		{
			objMessageMap = objMessamapReader.getMessageMap(enumMessageCode, null);
			if(isEventSupported(enumTriggerEvent))
				objMessage = new ACK(enumTriggerEvent, objMessageMap);
			else
				throw new MessageNotSupportedException(enumTriggerEvent.getValue());
		}
		else
		{
			switch(enumTriggerEvent)
			{
			case PC1 : 
				objMessage = new PPR_PC1(objMessageMap);
				break;
			case PC2 : 
				objMessage = new PPR_PC2(objMessageMap);
				break;
			case PC3  : 
				objMessage = new PPR_PC3 (objMessageMap);
				break;
			case PC6  : 
				objMessage = new PGL_PC6 (objMessageMap);
				break;
			case PC7  : 
				objMessage = new PGL_PC7 (objMessageMap);
				break;
			case PC8  : 
				objMessage = new PGL_PC8 (objMessageMap);
				break;
			case PCB  : 
				objMessage = new PPP_PCB (objMessageMap);
				break;
			case PCC  : 
				objMessage = new PPP_PCC (objMessageMap);
				break;
			case PCD  : 
				objMessage = new PPP_PCD (objMessageMap);
				break;
			case PCH  : 
				objMessage = new PPG_PCH (objMessageMap);
				break;
			case PCG  : 
				objMessage = new PPG_PCG (objMessageMap);
				break;
			case PCJ  : 
				objMessage = new PPG_PCJ (objMessageMap);
				break;
			}
		}
		return objMessage;
	}

	/*
	 * Retrieves Message map
	 */
	private IMap getMessageMap(EnumMessageCode enumMessageCode,EnumTriggerEvent enumTriggerEvent)
	{
		IMap objMessageMap = null;

		switch(enumTriggerEvent)
		{
		case PC1 : 
		case PC2 : 
		case PC3  : 
			objMessageMap = objMessamapReader.getMessageMap(EnumMessageCode.PPR,EnumTriggerEvent.PC1);
			break;
		case PC6  : 
		case PC7  : 
		case PC8  : 
			objMessageMap = objMessamapReader.getMessageMap(EnumMessageCode.PGL,EnumTriggerEvent.PC6);
			break;
		case PCB  : 
		case PCC  : 
		case PCD  : 
			objMessageMap = objMessamapReader.getMessageMap(EnumMessageCode.PPP,EnumTriggerEvent.PCB);
			break;
		case PCG  : 
		case PCH  :
		case PCJ  : 
			objMessageMap = objMessamapReader.getMessageMap(EnumMessageCode.PPG,EnumTriggerEvent.PCG);
			break;
		}
		return objMessageMap;
	}

	/**
	 * Checks whether Trigger Event specified in Enumeration is Supported.
	 * @param enumTriggerEvent enumerated value of Trigger Event
	 * @return boolean shows status as success or failure
	 */
	public boolean isEventSupported(EnumTriggerEvent enumTriggerEvent) 
	{
		if( enumTriggerEvent.equals(EnumTriggerEvent.PC1)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PC2)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PC3)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PC6)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PC7)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PC8)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PCB)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PCC)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PCD)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PCG)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PCH)
				|| enumTriggerEvent.equals(EnumTriggerEvent.PCJ)
		)
			return true;
		else 
			return false;
	}

	/*
	 * Checks whether Message Code specified in Enumeration is Supported.
	 */
	boolean isCodeSupported(EnumMessageCode enumMessageCode)
	{
		if(enumMessageCode == EnumMessageCode.PRR || enumMessageCode == EnumMessageCode.PPV ||
				enumMessageCode == EnumMessageCode.PTR || enumMessageCode == EnumMessageCode.PPT ||
				enumMessageCode == EnumMessageCode.ACK || enumMessageCode == EnumMessageCode.PGL ||
				enumMessageCode == EnumMessageCode.PPR || enumMessageCode == EnumMessageCode.PPP ||
				enumMessageCode == EnumMessageCode.QRY || enumMessageCode == EnumMessageCode.PPG)
			return true;

		return false;
	}
}
