package com.eactive.eai.common.routing;

import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import com.eactive.eai.common.context.ElinkTransactionContext;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageKeys;
import com.eactive.eai.common.util.Logger;


/** 
 * 1. 기능 : ElinkESBProcess를 호출하는 공통 Class
 * 2. 처리 개요 : 
 * *     - 
 * 3. 주의사항 
 *
 * @author  : DongHoon Lee
 * @version : v 1.0.0
 * @see : 관련 기능을 참조
 * @since   : 
 *  : 
 */
public class ElinkESBProcessProxy
{
	static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
	public static String PROXY_ERROR_CODE = "RECEAICPR001";	
	
	private static ConcurrentHashMap<String, Class> classLocalCache = new ConcurrentHashMap<String, Class>();
	
    /** 
     * 1. 기능 :  ElinkESBProcess의 호출 메소드(Local|Remote 방식)
     * 2. 처리 개요 : 
     *     - 
     * 3. 주의사항 
     *
	 * @param	serviceURI Route하기 위한 Process의 URI
	 * @param	eaiMessage EAIMessage Object
	 * @param	isLocal Local Process 호출인지 Remote Process 호출인지 여부
     * @param	prop Remote Process호출인 경우 (RouteKeys.WLI_URL, RouteKeys.WLI_USER,RouteKeys.WLI_PWD)를 설정 
	 * @return 결과 EAIMessage
     * @exception
     **/
	public static EAIMessage callElinkESBProcess(String serviceURI, EAIMessage eaiMessage, boolean isLocal, Properties prop) throws Exception
	{
		EAIMessage retMsg  = null;

		// [ElinkTransactionContext] 비동기 거래 시 컨텍스트 초기화 여부 판단
		// - ASYNC 거래이고, outbound Process 호출이 아닌 경우에만 초기화
		boolean shouldManageContext = eaiMessage != null
				&& EAIMessageKeys.ASYNC_SVC.equals(eaiMessage.getSvcTsmtUsgTp())
				&& (serviceURI == null || !serviceURI.startsWith("com.eactive.eai.outbound"));

		try {
			// [ElinkTransactionContext] 비동기 거래 진입점 - 컨텍스트 복원
			if (shouldManageContext) {
				ElinkTransactionContext.restore(eaiMessage.getTransactionContextTransfer());
				eaiMessage.setTransactionContextTransfer(null);  // 복원 후 전달용 필드 초기화
			}

			if (isLocal){
				Class cl = classLocalCache.get(serviceURI);

				if(cl == null) {
					cl = Class.forName(serviceURI);
					classLocalCache.put(serviceURI, cl);
				}
				Process proc = (Process)cl.newInstance();
	            proc.callService(eaiMessage, prop);

	            retMsg  = proc.clientReturn();
			}else{
				if(eaiMessage == null) {
					throw new Exception("EAIMessage is null");
				}
				else {
					retMsg = RemoteProxyClient.callProxyBean(eaiMessage, prop);
				}
			}
		} catch( ClassNotFoundException e) {
			if (logger.isError()) logger.error("ElinkProcessProxy] callElinkESBProcess["+serviceURI+"] Class Not Found Exception : ");
			throw new Exception(PROXY_ERROR_CODE);
		} catch( Exception e) {
			if (logger.isError()) logger.error("ElinkProcessProxy] callElinkESBProcess["+serviceURI+"] Exception : "+e.getMessage(),e);
			throw new Exception(PROXY_ERROR_CODE);
		} finally {
			// [ElinkTransactionContext] 비동기 거래 - 해제
			if (shouldManageContext) {
				ElinkTransactionContext.clear();
			}
		}
		return retMsg;
	}
}
