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

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 QryMessageFactory implements IMessageFactory 
{
	private static QryMessageFactory objQryMessageFactory = null;
	private static IMessageMapReader objMessageMapReader = null;
	private QryMessageFactory()
	{}

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


	/**
	 * 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 J01 : 
				objMessage = new QCN_J01(objMessageMap);
				break;
			case J02 : 
				objMessage = new QSX_J02(objMessageMap);
				break;
			case K11 : 
				objMessage = new RSP_K11(objMessageMap);
				break;
			case K13 : 
				objMessage = new RTB_K13(objMessageMap);
				break;
			case K15 : 
				objMessage = new RDY_K15(objMessageMap);
				break;
		
			case Q05:
				objMessage = new UDM_Q05(objMessageMap);
				break;
			case Q11 : 
				objMessage = new QBP_Q11(objMessageMap);
				break;
			case Q13 : 
				objMessage = new QBP_Q13(objMessageMap);
				break;
			case Q15 : 
				objMessage = new QBP_Q15(objMessageMap);
				break;
			case Q16 : 
				objMessage = new QSB_Q16(objMessageMap);
				break;
			case Q17 : 
				objMessage = new QVR_Q17(objMessageMap);
				break;
				
			case Z75 : 
				objMessage = new QBP_Z75(objMessageMap);
				break;
			case Z76 : 
				objMessage = new RTB_Z76(objMessageMap);
				break;
			case Z77 : 
				objMessage = new QBP_Z77(objMessageMap);
				break;
			case Z78 : 
				objMessage = new RTB_Z78(objMessageMap);
				break;
			case Z79 : 
				objMessage = new QBP_Z79(objMessageMap);
				break;
			case Z80 : 
				objMessage = new RDY_Z80(objMessageMap);
				break;
			case Z81 : 
				objMessage = new QBP_Z81(objMessageMap);
				break;
			case Z82 : 
				objMessage = new RSP_Z82(objMessageMap);
				break;
			case Z83 : 
				objMessage = new QSB_Z83(objMessageMap);
				break;
			case Z84 : 
				objMessage = new RSP_Z84(objMessageMap);
				break;
			case Z85 : 
				objMessage = new QBP_Z85(objMessageMap);
				break;
			case Z86 : 
				objMessage = new RSP_Z86(objMessageMap);
				break;
			case Z87 : 
				objMessage = new QBP_Z87(objMessageMap);
				break;
			case Z88 : 
				objMessage = new RSP_Z88(objMessageMap);
				break;
			case Z89 : 
				objMessage = new QBP_Z89(objMessageMap);
				break;
			case Z90 : 
				objMessage = new RSP_Z90(objMessageMap);
				break;
			case Z91 : 
				objMessage = new QBP_Z91(objMessageMap);
				break;
			case Z92 : 
				objMessage = new RTB_Z92(objMessageMap);
				break;
			case Z93 : 
				objMessage = new QBP_Z93(objMessageMap);
				break;
			case Z94 : 
				objMessage = new RTB_Z94(objMessageMap);
				break;
			case Z95 : 
				objMessage = new QBP_Z95(objMessageMap);
				break;
			case Z96 : 
				objMessage = new RTB_Z96(objMessageMap);
				break;
			case Z97 : 
				objMessage = new QBP_Z97(objMessageMap);
				break;
			case Z98 : 
				objMessage = new RDY_Z98(objMessageMap);
				break;
			case Z99 : 
				objMessage = new QBP_Z99(objMessageMap);
				break;
			default:
					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.J01)
				|| enumTriggerEvent.equals(EnumTriggerEvent.J02)
				|| enumTriggerEvent.equals(EnumTriggerEvent.K11)
				|| enumTriggerEvent.equals(EnumTriggerEvent.K13)
				|| enumTriggerEvent.equals(EnumTriggerEvent.K15)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q01)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q02)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q03)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q04)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q05)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q07)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q08)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q09)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q11)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q13)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q15)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q16)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Q17)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R07)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R08)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R09)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z75)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z76)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z77)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z78)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z79)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z80)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z81)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z82)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z83)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z84)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z85)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z86)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z87)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z88)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z89)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z90)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z91)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z92)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z93)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z94)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z95)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z96)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z97)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z98)
				|| enumTriggerEvent.equals(EnumTriggerEvent.Z99)

		)
			return true;
		else 
			return false;
	}
	
	/*
	 * Checks whether Message Code specified in Enumeration is Supported.
	 */
	boolean isCodeSupported(EnumMessageCode enumMessageCode)
	{
		if(enumMessageCode == EnumMessageCode.ACK || enumMessageCode == EnumMessageCode.RSP ||
				enumMessageCode == EnumMessageCode.RDY || enumMessageCode == EnumMessageCode.TBR ||
				enumMessageCode == EnumMessageCode.EDR || enumMessageCode == EnumMessageCode.RTB ||
				enumMessageCode == EnumMessageCode.DSR || enumMessageCode == EnumMessageCode.QBP ||
				enumMessageCode == EnumMessageCode.QSB || enumMessageCode == EnumMessageCode.QSX ||
				enumMessageCode == EnumMessageCode.UDM || enumMessageCode == EnumMessageCode.EQQ ||
				enumMessageCode == EnumMessageCode.RQQ || enumMessageCode == EnumMessageCode.SPQ ||
				enumMessageCode == EnumMessageCode.VQQ || enumMessageCode == EnumMessageCode.QCN ||
				enumMessageCode == EnumMessageCode.QRY)
			return true;
		
		return false;
	}
	//This method returns the MessageMap for the particular event and messageCode. 
	private IMap getMessageMap(EnumMessageCode enumMessageCode,EnumTriggerEvent enumTriggerEvent)
	{
		IMap objMessageMap =null;
		
		switch(enumMessageCode)
		{
		case DSR :
			switch (enumTriggerEvent) 
			{
			case Q01:
			case Q03:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q01);
			}
			break;
		case EDR :
			switch (enumTriggerEvent) 
			{
			case R07:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.R07);
			}
			break;
		case EQQ :
			switch (enumTriggerEvent) 
			{
			case Q04:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q04);
			}
			break;
		case QBP :
			switch (enumTriggerEvent) 
			{
			case Q11:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q11);
			case Q13:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q13);
			case Q15:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q15);
			case Z75:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z75);
			case Z77:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z77);
			case Z91:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z91);
			case Z93:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z93);
			case Z95:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z95);
			case Z97:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z97);
			case Z99:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z99);
			case Z79:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z79);
			case Z81:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z81);
			case Z85:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z85);
			case Z89:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z89);
			case Z87:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z87);
			}
			break;
		case QCN :
			switch (enumTriggerEvent) 
			{
			case J01:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.J01);
			}
			break;
		case QVR :
			switch (enumTriggerEvent) 
			{
			case Q17:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q17);
			}
			break;
		case QRY :
			switch (enumTriggerEvent) 
			{
			case Q01:
			case Q02:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q01);
			}
			break;
		case QSB :
			switch (enumTriggerEvent) 
			{
			case Q16:
			case Z83:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q16);
			}
			break;
		case QSX :
			switch (enumTriggerEvent) 
			{
			case J02:
				return objMessageMapReader.getMessageMap(EnumMessageCode.QCN,EnumTriggerEvent.J01);
			}
			break;
		case RDY :
			switch (enumTriggerEvent) 
			{
			case K15:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.K15);
			case Z98:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.K15);
			case Z80:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z80);
			}
			break;
		case RQQ :
			switch (enumTriggerEvent) 
			{
			case Q09:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q09);
			}
			break;
		case RSP :
			switch (enumTriggerEvent) 
			{
			case K11:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.K11);
			case Z82:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z82);
			case Z86:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z86);
			case Z88:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z88);
			case Z90:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z90);
			case Z84:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Z84);
			}
			break;
		case RTB :
			switch (enumTriggerEvent) 
			{
			case K13:
			case Z76:
			case Z78:
			case Z92:
			case Z94:
			case Z96:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.K13);
			}
			break;
		case SPQ :
			switch (enumTriggerEvent) 
			{
			case Q08:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q08);
			}
			break;
		case TBR :
			switch (enumTriggerEvent) 
			{
			case R08:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.R08);
			}
			break;
		case UDM :
			switch (enumTriggerEvent) 
			{
			case Q05:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q05);
			}
			break;
		case VQQ :
			switch (enumTriggerEvent) 
			{
			case Q07:
				return objMessageMapReader.getMessageMap(enumMessageCode,EnumTriggerEvent.Q07);
			}
			break;
		default:
			break;
		}	
		return objMessageMap;
	}
}
