/*******************************************************************************
 *  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.patientreferral;

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 PatientRefMessageFactory implements IMessageFactory
{
	private static PatientRefMessageFactory objPatientRefMessageFactory = null;
	private static IMessageMapReader objMessageMapReader = null;


	private PatientRefMessageFactory()
	{

	}

	/**
	 * Creates Object of ADTMessageFactory.
	 * @return ADTMessageFactory object of ADTMessageFactory
	 */
	public static PatientRefMessageFactory createInstance()
	{
		if(objPatientRefMessageFactory == null)
		{
			objMessageMapReader = MessageMapReader.createInstance(EnumHL7System.HL7_SYSTEM_PATIENTREFERRAL);
			objPatientRefMessageFactory = new PatientRefMessageFactory();
		}
		return objPatientRefMessageFactory;
	}


	/**
	 * 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 = objMessageMapReader.getMessageMap(enumMessageCode, null);
			if(isEventSupported(enumTriggerEvent))
				objMessage = new ACK(enumTriggerEvent, objMessageMap);
			else
				throw new MessageNotSupportedException(enumTriggerEvent.getValue());
		}
		else
		{
			switch(enumTriggerEvent)
			{
			case I01 : 
				switch(enumMessageCode)
				{
				case RPI:
					objMessage = new RPI_I01(objMessageMap);
					break; 
				case RQI:
					objMessage = new RQI_I01(objMessageMap);
					break; 
				}
				break; 
			case I02 :
				switch (enumMessageCode)
				{

				case RPL:
					objMessage = new RPL_I02(objMessageMap);
					break;

				case RQI:
					objMessage = new RQI_I02(objMessageMap);
					break;
				}
				break;

			case I03 :
				switch (enumMessageCode)
				{

				case RPR:
					objMessage = new RPR_I03(objMessageMap);
					break;

				case RQI:
					objMessage = new RQI_I03(objMessageMap);
					break;
				}
				break;
			case I04 : 
				switch(enumMessageCode)
				{
				case RPI:
					objMessage = new RPI_I04(objMessageMap);
					break; 
				case RQP:
					objMessage = new RQP_I04(objMessageMap);
					break; 
				}
				break; 

			case I07 : 
				switch(enumMessageCode)
				{
				case PIN:
					objMessage = new PIN_I07(objMessageMap);
					break; 
				}
				break; 
			case I08 : 
				switch(enumMessageCode)
				{
				case RPA:
					objMessage = new RPA_I08(objMessageMap);
					break; 
				case RQA:
					objMessage = new RQA_I08(objMessageMap);
					break; 
				}
				break;  
			case I09 : 
				switch(enumMessageCode)
				{
				case RPA:
					objMessage = new RPA_I09(objMessageMap);
					break; 
				case RQA:
					objMessage = new RQA_I09(objMessageMap);
					break; 
				}
				break;  
			case I10 : 
				switch(enumMessageCode)
				{
				case RPA:
					objMessage = new RPA_I10(objMessageMap);
					break; 
				case RQA:
					objMessage = new RQA_I10(objMessageMap);
					break; 
				}
				break;  
			case I11 : 
				switch(enumMessageCode)
				{
				case RPA:
					objMessage = new RPA_I11(objMessageMap);
					break; 
				case RQA:
					objMessage = new RQA_I11(objMessageMap);
					break; 
				}
				break;  
			case I12:
				switch(enumMessageCode)
				{
				case REF:
					objMessage = new REF_I12(objMessageMap);
					break;
				case RRI:
					objMessage = new RRI_I12(objMessageMap);
					break;
				}
				break;
			case I13 : 
				switch(enumMessageCode)
				{
				case REF:
					objMessage = new REF_I13(objMessageMap);
					break;
				case RRI:
					objMessage = new RRI_I13(objMessageMap);
					break;
				}
				break; 
			case I14 : 
				switch(enumMessageCode)
				{
				case REF:
					objMessage = new REF_I14(objMessageMap);
					break;
				case RRI:
					objMessage = new RRI_I14(objMessageMap);
					break;
				}
				break;
			case I15 : 
				switch(enumMessageCode)
				{
				case REF:
					objMessage = new REF_I15(objMessageMap);
					break;
				case RRI:
					objMessage = new RRI_I15(objMessageMap);
					break;
				}
				break; 
			case I16 : 
				switch(enumMessageCode)
				{
				case CCR:
					objMessage = new CCR_I16(objMessageMap);
					break;
				}
				break; 
			case I17 : 
				switch(enumMessageCode)
				{
				case CCR:
					objMessage = new CCR_I17(objMessageMap);
					break;
				}
				break; 
			case I18 : 
				switch(enumMessageCode)
				{
				case CCR:
					objMessage = new CCR_I18(objMessageMap);
					break;
				}
				break; 
			case I19 : 
				switch(enumMessageCode)
				{
				case CCQ:
					objMessage = new CCQ_I19(objMessageMap);
					break;
				case CQU:
					objMessage = new CQU_I19(objMessageMap);
					break;
				}
				break; 
			case I20 : 
				switch(enumMessageCode)
				{
				case CCU:
					objMessage = new CCU_I20(objMessageMap);
					break;
				}
				break; 
			case I21 : 
				switch(enumMessageCode)
				{
				case CCM:
					objMessage = new CCM_I21(objMessageMap);
					break;
				}
				break; 
			case I22 : 
				switch(enumMessageCode)
				{
				case CCF:
					objMessage = new CCF_I22(objMessageMap);
					break;
				case CCI:
					objMessage = new CCI_I22(objMessageMap);
					break;
				}
				break; 
			}
		}
		return objMessage;
	}

	/**
	 * 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.I01)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I02)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I03)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I04)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I07)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I08)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I09)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I10)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I11)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I12)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I13)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I14)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I15)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I16)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I17)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I18)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I19)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I20)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I21)
				|| enumTriggerEvent.equals(EnumTriggerEvent.I22)
		)
			return true;
		else 
			return false;
	}

	/*
	 * Checks whether Message Code specified in Enumeration is Supported.
	 */
	boolean isCodeSupported(EnumMessageCode enumMessageCode)
	{
		if(enumMessageCode == EnumMessageCode.RPI || enumMessageCode == EnumMessageCode.RPL ||
				enumMessageCode == EnumMessageCode.RPR || enumMessageCode == EnumMessageCode.RCI ||
				enumMessageCode == EnumMessageCode.RCL || enumMessageCode == EnumMessageCode.RPA ||
				enumMessageCode == EnumMessageCode.RRI || enumMessageCode == EnumMessageCode.ACK ||
				enumMessageCode == EnumMessageCode.RQI || enumMessageCode == EnumMessageCode.RQP ||
				enumMessageCode == EnumMessageCode.RQC || enumMessageCode == EnumMessageCode.PIN ||
				enumMessageCode == EnumMessageCode.REF || enumMessageCode == EnumMessageCode.RQA ||
				enumMessageCode == EnumMessageCode.CCR || enumMessageCode == EnumMessageCode.CCQ ||
				enumMessageCode == EnumMessageCode.CQU || enumMessageCode == EnumMessageCode.CCU ||
				enumMessageCode == EnumMessageCode.CCM || enumMessageCode == EnumMessageCode.CCF ||
				enumMessageCode == EnumMessageCode.CCI )
			return true;

		return false;
	}

	private IMap getMessageMap(EnumMessageCode enumMessageCode, EnumTriggerEvent enumTriggerEvent)
	{
		IMap objMessageMap =null;

		switch(enumTriggerEvent)
		{
		case I01 : 
			objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I01);
			break; 
		case I02 :
			switch (enumMessageCode)
			{
			case RPL:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I02);
				break;

			case RQI:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I01);
				break;
			}
			break;
		case I03 :
			switch (enumMessageCode)
			{

			case RPR:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I03);
				break;

			case RQI:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I01);
				break;
			}
			break;
		case I04 : 
			switch(enumMessageCode)
			{
			case RPI:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I01);
				break; 
			case RQP:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I04);
				break; 
			}
			break;
		case I07 : 
			switch(enumMessageCode)
			{
			case PIN:					
				objMessageMap = objMessageMapReader.getMessageMap(EnumMessageCode.RQI, EnumTriggerEvent.I01);
				break; 
			}
			break; 
		case I08 : 
		case I09 : 
		case I10 : 
		case I11 : 
			objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I08);
			break;  
		case I12 :
		case I13 : 
		case I14 : 
		case I15 : 
			objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I12);
			break; 
		case I16 :
		case I17 :
		case I18 :
			objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I16);
			break;
		case I19 :
			switch (enumMessageCode)
			{
			case CCQ:
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I19);
				break;
			case CQU:
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I19);
				break;
			}
			break;
		case I20 :
			switch(enumMessageCode)
			{
			case CCU:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I20);
				break; 
			}
			break; 
		case I21 :
			switch(enumMessageCode)
			{
			case CCM:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I21);
				break; 
			}
			break; 
		case I22 :
			switch(enumMessageCode)
			{
			case CCF:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I22);
				break; 
			case CCI:					
				objMessageMap = objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.I22);
				break; 
			}
			break; 
		}		
		
		return objMessageMap;
	}
}
