package com.eactive.eai.common.logger;

import java.util.Properties;

import org.apache.commons.lang3.SerializationUtils;

import com.eactive.eai.common.logger.async.AsyncLoggingPoolManager;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageKeys;
import com.eactive.eai.common.monitor.EAIServiceMonitor;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.common.util.MessageUtil;
import com.eactive.eai.env.ElinkConfig;

/**
 * 1. 기능 : EAI에서 처리되는 모든 On-Line 거래를 데이터베이스에 로깅하기 위한 운영관리 Logger Sender 
 * 2. 처리 개요 : - RequestProcessor에서 받은 로깅 정보를 로그 Queue로 전달 
 * 3. 주의사항
 */
public class EAILogSender {
    static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
	static TransactionLogger txLogger;
	static {
		try {
			txLogger = (TransactionLogger) Class.forName("com.eactive.eai.common.logger.DBLogTransactionLogger").newInstance();
		} catch(Exception e) {
			logger.error(e.getMessage(), e);
		}
	}
	
	private EAILogSender() {
		
	}
	public static int logCount() {
		return txLogger.logCount();
	}

	public static int errCount() {
		return txLogger.errCount();
	}

	public static void resetCount() {
		txLogger.resetCount();
	}

	public static void send(EAIMessage message, Properties prop) throws Exception {
		if(message == null) {
			if(logger.isWarn()) {
				logger.warn("EAIMessage is null, skip async logging.");
			}
		}
		else {
			String guidLogPrefix = "EAILogSender] GUID[" + message.getMapper().getGuid(message.getStandardMessage())
	        		+ "] UUID[" + message.getSvcOgNo() + "] ";

			boolean isLogging = false;
			int svcLogLvl = message.getSvcLogLvl();
			int logPssSno = message.getLogPssSno();
			String svcTsmtUsgTp = message.getSvcTsmtUsgTp();
			if(svcLogLvl >= 3) {
                isLogging = true;
            }
            else if(svcLogLvl == 2) {
                if( EAIMessageKeys.SYNC_SVC.equals(svcTsmtUsgTp) && 
                (logPssSno == 100 || logPssSno == 400) ) {
                    isLogging = true;
                }
                if( EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTp) && 
                (logPssSno == 200 || logPssSno == 400) ) {
                    isLogging = true;
                }
            }
            else if(svcLogLvl == 1) {
                isLogging = ! MessageUtil.checkRspErrCd(message.getRspErrCd());
            }
            else {
            	isLogging = false;
            }
            if(logger.isDebug()) {
    			logger.debug(guidLogPrefix + " svcLogLvl="+ svcLogLvl + ",isLogging="+ isLogging+ ", logPssSno="+ logPssSno);
            }
			long logTime = System.currentTimeMillis();
        	message.setMsgPssTm(logTime);
			if(isLogging) {
	        	if(ElinkConfig.isUseAsyncLogging()) {
					try {
						EAIMessage cloned = null; 
	//					cloned = (EAIMessage) ObjectUtil.deepCopy(message);
//						cloned = (EAIMessage) SerializationUtils.clone(message);
						// performance issue, use clone -> shallow copy bug -> fix  
						cloned = (EAIMessage) message.clone();
						Properties clonedProp = null;
						if(prop != null) clonedProp = (Properties) prop.clone();
						AsyncLoggingPoolManager.getInstance().publish(cloned, clonedProp);
					} catch (Exception e) {
						logger.warn("AsyncLogging error", e);
						logDirect(message, prop);
//						throw e;
					}
				}
				else {
					logDirect(message, prop);
				}
			}
			
			// 실시간 모니터링 로그
			EAIServiceMonitor servicemonitor = EAIServiceMonitor.getInstance();
			if(EAIMessageKeys.EAI_BLOCKED_CODE.equals(message.getRspErrCd())) {
            	if(logger.isWarn()) {
            		logger.warn(guidLogPrefix + " 거래통제 실시간 모니터링 SKIP - " + message.getEAISvcCd()
            		+ ", "+message.getMapper().getGuid(message.getStandardMessage()) );
            	}
            }else if (EAIMessageKeys.EAI_INFLOW_BLOCKED_CODE.equals(message.getRspErrCd())) {
            	if(logger.isWarn()) {
            		logger.warn(guidLogPrefix + " 유량제어 실시간 모니터링 SKIP - " + message.getEAISvcCd()
            		+ ", "+ message.getMapper().getGuid(message.getStandardMessage()) );
            	}
            }else {
            	servicemonitor.receiveLogMessage(message);
            }
		}
	}
	
	public static void logDirect(EAIMessage message, Properties prop) throws EAILogException {
		txLogger.log(message, prop); 
	}
}
