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

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.EnumMessageStructure;
import cdac.medinfo.sdk.hl7282.utils.EnumTriggerEvent;
import cdac.medinfo.sdk.hl7282.utils.IMap;
import cdac.medinfo.sdk.hl7282.utils.IMessageMapReader;

class ObsvRepMessageFactory implements IMessageFactory  
{
	private static ObsvRepMessageFactory objObsvRepMessageFactory = null;
	private static IMessageMapReader objMessageMapReader = null;
	private ObsvRepMessageFactory()
	{}

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

	/**
	 * 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 C01 : 
			objMessage = new CRM_C01(objMessageMap);
			break;
		case C02 : 
			objMessage = new CRM_C02(objMessageMap);
			break;
		case C03 : 
			objMessage = new CRM_C03(objMessageMap);
			break;
		case C04 : 
			objMessage = new CRM_C04(objMessageMap);
			break;
		case C05 : 
			objMessage = new CRM_C05(objMessageMap);
			break;
		case C06 : 
			objMessage = new CRM_C06(objMessageMap);
			break;
		case C07 : 
			objMessage = new CRM_C07(objMessageMap);
			break;
		case C08 : 
			objMessage = new CRM_C08(objMessageMap);
			break;
		case C09 : 
			objMessage = new CSU_C09(objMessageMap);
			break;
		case C10 : 
			objMessage = new CSU_C10(objMessageMap);
			break;
		case C11 : 
			objMessage = new CSU_C11(objMessageMap);
			break;
		case C12 : 
			objMessage = new CSU_C12(objMessageMap);
			break;
		case P07 : 
			objMessage = new PEX_P07(objMessageMap);
			break;
		case P08 : 
			objMessage = new PEX_P08(objMessageMap);
			break;
		case R01 : 
			objMessage = new ORU_R01(objMessageMap);
			break;

		case R22 : 
			objMessage = new OUL_R22(objMessageMap);
			break;
		case R23 : 
			objMessage = new OUL_R23(objMessageMap);
			break;
		case R24 : 
			objMessage = new OUL_R24(objMessageMap);
			break;
		case R25 : 
			objMessage = new OPU_R25(objMessageMap);
			break;
		case R26: 
			objMessage = new OSM_R26(objMessageMap);
			break;
		case R30 : 
			objMessage = new ORU_R30(objMessageMap);
			break;
		case R31 : 
			objMessage = new ORU_R31(objMessageMap);
			break;
		case R32 : 
			objMessage = new ORU_R32(objMessageMap);
			break;
		case R33 : 
			objMessage = new ORA_R33(objMessageMap);
			break;
		case R40: 
			objMessage = new ORU_R40(objMessageMap);
			break;
		case R41: 
			objMessage = new ORA_R41(objMessageMap);
			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.C01)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C02)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C03)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C04)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C05)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C06)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C07)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C08)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C09)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C10)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C11)
				|| enumTriggerEvent.equals(EnumTriggerEvent.C12)
				|| enumTriggerEvent.equals(EnumTriggerEvent.P07)
				|| enumTriggerEvent.equals(EnumTriggerEvent.P08)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R01)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R22)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R23)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R24)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R25)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R26)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R30)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R31)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R32)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R33)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R40)
				|| enumTriggerEvent.equals(EnumTriggerEvent.R41)
		)
			return true;
		else
			return false;

	}

	/*
	 * Checks whether Message Code specified in Enumeration is Supported.
	 */
	boolean isCodeSupported(EnumMessageCode enumMessageCode)
	{
		if(enumMessageCode == EnumMessageCode.ORF || enumMessageCode == EnumMessageCode.ORU ||
				enumMessageCode == EnumMessageCode.QRY || enumMessageCode == EnumMessageCode.ACK ||
				enumMessageCode == EnumMessageCode.OUL || enumMessageCode == EnumMessageCode.CRM ||
				enumMessageCode == EnumMessageCode.SUR || enumMessageCode == EnumMessageCode.CSU ||
				enumMessageCode == EnumMessageCode.PEX|| enumMessageCode == EnumMessageCode.OSM ||
				enumMessageCode == EnumMessageCode.ORA || enumMessageCode == EnumMessageCode.OPU)
			return true;
		
		return false;
	}
	private IMap getMessageMap(EnumMessageCode enumMessageCode,EnumTriggerEvent enumTriggerEvent)
	{
		IMap objMessageMap=null;
		if(enumMessageCode == EnumMessageCode.ACK)
		{
			objMessageMapReader.getMessageMap(enumMessageCode, enumTriggerEvent);
		}
		else
		{
			switch(enumMessageCode)
			{
				case CRM :
					switch(enumTriggerEvent)
					{
					case C01:
					case C02: 
					case C03:
					case C04:
					case C05:
					case C06:
					case C07:
					case C08:

						return objMessageMapReader.getMessageMap(enumMessageCode,  EnumTriggerEvent.C01);

					}
					break;
				case ORF :
						return objMessageMapReader.getMessageMap(enumMessageCode, enumTriggerEvent);
				case OSM :
					return objMessageMapReader.getMessageMap(enumMessageCode, enumTriggerEvent);
				case ORA :
					switch(enumTriggerEvent)
					{
					case R33: 
					case R41:
						return objMessageMapReader.getMessageMap(enumMessageCode, enumTriggerEvent);
					}
					break;

				case ORU :
					switch(enumTriggerEvent)
					{
					case R01:
					case R40:

						return objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.R01);


					case R30:	
					case R31:	
					case R32:	

						return objMessageMapReader.getMessageMap(enumMessageCode,  EnumTriggerEvent.R30);


					}
					break;
				case OUL :
					switch(enumTriggerEvent)
					{
					case R22: 
					case R23:
					case R24:

						return objMessageMapReader.getMessageMap(enumMessageCode,  enumTriggerEvent);


					}
					break;
				case CSU :
					switch(enumTriggerEvent)
					{
					case C09:
					case C10: 
					case C11:
					case C12:

						return objMessageMapReader.getMessageMap(enumMessageCode,  EnumTriggerEvent.C09);


					}
					break;
				case PEX :
					switch(enumTriggerEvent)
					{
					case P07:
					case P08: 
						return objMessageMapReader.getMessageMap(enumMessageCode, EnumTriggerEvent.P07);

					}
					break;
				case QRY :
						return objMessageMapReader.getMessageMap(enumMessageCode, enumTriggerEvent);
						
				case OPU:
					return objMessageMapReader.getMessageMap(enumMessageCode, enumTriggerEvent);
					
			}
		}
		return objMessageMap;
	}
}
