package com.eactive.eai.common.monitor;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.eactive.eai.common.errorcode.ErrorCodeHandler;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.lifecycle.Lifecycle;
import com.eactive.eai.common.lifecycle.LifecycleException;
import com.eactive.eai.common.lifecycle.LifecycleListener;
import com.eactive.eai.common.lifecycle.LifecycleSupport;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageKeys;
import com.eactive.eai.common.message.EAIMessageManager;
import com.eactive.eai.common.message.IFType;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.server.Keys;
import com.eactive.eai.common.util.ApplicationContextProvider;
import com.eactive.eai.common.util.DatetimeUtil;
import com.eactive.eai.common.util.Logger;

/**
 * EAIServiceMonitor 컴포넌트는 EAI 모든 거래 마다 각 EAI Service Code 기준으로 처리 통계 데이터를 캐싱 -
 * 일 누적 데이터와 최근(10분, 1시간) 누적데이터를 각 EAIServiceCode 별로 MonitorVO 객체로 관리 - 일 누적
 * 데이터와 최근(10분, 1시간) 누적 데이터를 초기화하기 위해 TimerTaskChecker 쓰레드 데몬을 관리
 */
@Component
public class EAIServiceMonitor implements Lifecycle {
	private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

	// 일자전환시 RMS에서 참조할 수 있도록 관리되는 변수
	private String monitorDate = "";
	private LifecycleSupport lifecycle = new LifecycleSupport(this);

	public static final String PROP_GROUP = "EAIServiceMonitor";

	// EAIServiceMonitor에서 사용하는 Property Key : MonitorChecker의 동작 주기
	public static final String PROP_PERIOD = "monitor.checker.period";

	// EAIServiceMonitor에서 사용하는 Property Key : MonitorChecker의 동작 주기
	public static final String FILE_WRITE_PERIOD = "file.write.period";

	// 주기적으로 write할 file의 위치
	public static final String FILE_PATH = "file.write.path";

	// 파일로깅시 데이터를 구분하기 위한 구분자
	public static final String MASTER_DELIMITER = "file.write.master.delimiter";

	// 파일로깅시 데이터를 구분하기 위한 구분자
	public static final String SUB_DELIMITER = "file.write.sub.delimiter";

	// EAI FRAMEWORK의 예외처리에서 사용되는 에러 코드
	private static String[] errorCode = { "E", "F" };

	// EAI Service Code별 모니터링 오브젝트(MonitorVO)를 위한 HashMap
	private ConcurrentHashMap<String, MonitorVO> monitors = new ConcurrentHashMap<>();

	// 업무구분별 MonitorVO를 위한 HashMap
	private ConcurrentHashMap<String, HashMap<String, MonitorVO>> bwkClss = new ConcurrentHashMap<>();

	// 일일, 최근시간별 데이터 저장을 위해 주기적으로 실행 Monitor check를 하는 TimerTask object
	private MonitorChecker checker;

	// 주기적으로 파일에 write하기 위한 TimerTask object
	private MonitorWriteChecker writer;

	// MonitorChecker를 실제 실행하는 Timer object
	private Timer timer;

	// MonitorChecker를 실제 실행하는 Timer object - add 20080618 by kscheon
	private Timer write_timer;

	// EAIServiceMonitor starting 여부를 체크하는 flag 변수
	private boolean started;

	@Autowired
	private EAIMessageManager eaiMsgManager;

	private String filePath;

	private String fileName;

	private String master_delimiter;
	private String sub_delimiter;

	// 에러코드 중 타임아웃으로 분류해야 하는 에러코드 리스트 : 2008.12.11
	public static final String TO_ERRORLIST = "timeout.errorlist";

	private String timeOutCodes = "";
	private String defTimeOutCodes = "RECEAIOSA777,RECEAIOHP003,RECEAIOSP004,RECEAIOTC913,RECEAIOSA010,RECEAIOEP010,RECEAIOHP010,RECEAIOSP010,RECEAIOTP010";

	public static final String BIZ_ERRORLIST = "biz.errorlist";

	private String bizErrorCodes = "";

	private String defBizErrorCodes = "RECEAICEU104,RECEAICKE301,RECEAIIRP040,RECEAIOEP020,RECEAIOEP030,RECEAIOHP020,RECEAIOHP022,RECEAIOHP030,RECEAIOMP002,RECEAIOMP006,RECEAIOSA020,RECEAIOSP020,RECEAIOSP030,RECEAIOTP002,RECEAIOTP006,RECEAICBE001,RECEAICBE010,RECEAICBX001,RECEAICME001,RECEAICMK001,RECEAIFBR002,RECEAIIRA001,RECEAIIRP050,RECEAIIRP060,RECEAIIRP062";

	private MonitorCleaner cleaner;
	private Timer cleanerTimer;
	
	@Autowired
	private StatisticsMonitor statisticsMonitor;

	public static synchronized EAIServiceMonitor getInstance() {
		return ApplicationContextProvider.getContext().getBean(EAIServiceMonitor.class);
	}

	public void start() throws LifecycleException {
		if (started) {
			String errorText = ErrorCodeHandler.getMessage("RECEAICMT201");
			if (logger.isError())
				logger.error(ExceptionUtil.make("RECEAICMT201", errorText));
		}

		lifecycle.fireLifecycleEvent(STARTING_EVENT, this);

		// 데일리 클리너 초기화
		this.cleaner = new MonitorCleaner();

		// 다음 새벽 2시 계산
		Calendar firstTime = Calendar.getInstance();
		firstTime.set(Calendar.HOUR_OF_DAY, 2);
		firstTime.set(Calendar.MINUTE, 0);
		firstTime.set(Calendar.SECOND, 0);

		// 이미 오늘 2시가 지났으면 다음날로 설정
		if (firstTime.before(Calendar.getInstance())) {
			firstTime.add(Calendar.DATE, 1);
		}

		this.cleanerTimer = new Timer("MonitorCleanerTimer");
		// 매일 새벽 2시에 실행 (24시간 = 24 * 60 * 60 * 1000 = 86400000 밀리초)
		this.cleanerTimer.scheduleAtFixedRate(this.cleaner, firstTime.getTime(), 86400000);

		PropManager pmanager = PropManager.getInstance();

		filePath = pmanager.getProperty(PROP_GROUP, FILE_PATH);
		if (filePath == null || filePath.equals("")) {
			filePath = ".";
		}
		master_delimiter = pmanager.getProperty(PROP_GROUP, MASTER_DELIMITER);
		sub_delimiter = pmanager.getProperty(PROP_GROUP, SUB_DELIMITER);
		timeOutCodes = pmanager.getProperty(TO_ERRORLIST);
		bizErrorCodes = pmanager.getProperty(BIZ_ERRORLIST);

		// set current timeout error code list
		if (timeOutCodes == null || timeOutCodes.length() <= 0) {
			timeOutCodes = defTimeOutCodes;
			if (logger.isWarn()) {
				logger.warn("EAIServiceMonitor] Timeout Error Code List Property NOT SET Group[" + PROP_GROUP
						+ "] Property[" + TO_ERRORLIST + "]");
				logger.warn("EAIServiceMonitor] Set Default Value ...");
			}
		}

		if (logger.isWarn()) {
			logger.warn("EAIServiceMonitor] Timeout Error Code List >> " + timeOutCodes);
		}

		// 업무에러 코드에 대한 정의가 필요
		if (bizErrorCodes == null || bizErrorCodes.length() <= 0) {
			bizErrorCodes = defBizErrorCodes;
			if (logger.isWarn()) {
				logger.warn("EAIServiceMonitor] Biz Error Code List Property NOT SET Group[" + PROP_GROUP
						+ "] Property[" + BIZ_ERRORLIST + "]");
				logger.warn("EAIServiceMonitor] Set Default Value ...");
			}
		}

		if (logger.isWarn()) {
			logger.warn("EAIServiceMonitor] System Error Code List >> " + bizErrorCodes);
		}

		if (master_delimiter == null || master_delimiter.length() <= 0) {
			master_delimiter = ":";
		}

		if (sub_delimiter == null || sub_delimiter.length() <= 0) {
			sub_delimiter = "/";
		}

		// 파일에 저장된 모니터링 정보를 메모리에 로딩
		monitors = createMonitorVO();

		// 최초 한번 실행하고 10분단위 정각에 실행, 정시에 reset
		this.checker = new MonitorChecker();
		this.checker.setEAIServiceMonitor(this);

		Calendar cal = Calendar.getInstance();
		int min = cal.get(Calendar.MINUTE) / 10 * 10;
		cal.set(Calendar.MINUTE, min);
		cal.set(Calendar.SECOND, 0);

		this.timer = new Timer("EAIServiceMonitorTimer");
		this.timer.scheduleAtFixedRate(this.checker, cal.getTime(), 600000);

		this.writer = new MonitorWriteChecker();
		this.writer.setEAIServiceMonitor(this);

		// reset과 중복되지 않도록 10초 후에 write하도록 처리함
		cal.set(Calendar.SECOND, 10);
		this.write_timer = new Timer("EAIServiceMonitorWriteTimer");
		this.write_timer.scheduleAtFixedRate(this.writer, cal.getTime(), 600000);

		started = true;
		lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
	}

	public void stop() throws LifecycleException {
		if (!started) {
			String errorText = ErrorCodeHandler.getMessage("RECEAICMT202");
			if (logger.isError())
				logger.error(ExceptionUtil.make("RECEAICMT202", errorText));
		}

		lifecycle.fireLifecycleEvent(STOPING_EVENT, this);

		this.timer.cancel();
		this.write_timer.cancel();
		this.cleanerTimer.cancel();  // 클리너 타이머도 정지

		this.timer = null;
		this.checker = null;
		this.cleanerTimer = null;
		this.cleaner = null;
		if (this.monitors != null) {
			this.monitors.clear();
			this.monitors = null;
		}

		this.write_timer = null;
		this.writer = null;

		started = false;
		lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
	}

	public void addLifecycleListener(LifecycleListener listener) {
		lifecycle.addLifecycleListener(listener);
	}

	public LifecycleListener[] findLifecycleListeners() {
		return lifecycle.findLifecycleListeners();
	}

	public void removeLifecycleListener(LifecycleListener listener) {
		lifecycle.removeLifecycleListener(listener);
	}

	public boolean isStarted() {
		return this.started;
	}

	public void receiveLogMessage(EAIMessage msg) {
		try {
			if (msg == null) {
				String errorText = ErrorCodeHandler.getMessage("RWCEAICMT203");
				if (logger.isWarn())
					logger.warn(ExceptionUtil.make("RWCEAICMT203", errorText));
			}

			String svcTsmtUsgTP = ""; // 서비스동시사용 - ServiceTheSameTimeUsgaeType - [SYNC|ASYN|AKON]
			String psvItfTp = ""; // 수동인터페이스유형 - PassiveInterfaceType - [SYNC|ASYN|AKON]
			String rspErrCd = ""; // 응답에러코드
			String eaiSvcCd = "";
			String error = "";
			String svcOgNo = "";
			String bwkCls = ""; // 업무구분
			long msgPssTm; // 메시지처리시각
			long msgRcvTm; // 메시지수신시각
			int logPssSno; // 로그처리일련번호
			boolean isSingle = true;
			int iErrorCode = 0; // 0 : 정상, 1 : 에러, 2 : 타임아웃

			MonitorVO monitor = null;

			svcTsmtUsgTP = msg.getSvcTsmtUsgTp();
			psvItfTp = msg.getCurrentSvcMsg().getPsvItfTp();
			msgPssTm = msg.getMsgPssTm();
			msgRcvTm = msg.getMsgRcvTm();
			logPssSno = msg.getLogPssSno();
			rspErrCd = msg.getRspErrCd();
			eaiSvcCd = msg.getEAISvcCd();
			svcOgNo = msg.getSvcOgNo();
			bwkCls = msg.getBwkCls();

			String screnNo = " ";
			String intfacSendTranCd = msg.getMapper().getServiceId(msg.getStandardMessage());

			if (StringUtils.isEmpty(intfacSendTranCd))
				intfacSendTranCd = " ";

			String adapterGroupName = "";

			// S01, R01 => 기동어댑터
			if (eaiSvcCd.endsWith("1")) {
				adapterGroupName = msg.getSngSysItfTp();
			} else {
				adapterGroupName = msg.getCurrentSvcMsg().getPsvSysItfTp();
			}

			// 메시지의 에러/정상 상태 확인을 위한 데이터
			if (rspErrCd.length() >= 12) {
				error = rspErrCd.substring(1, 2);
			}

			// 에러와 타임아웃을 분리 : 이동훈
			if (errorCode[0].equals(error.toUpperCase()) || errorCode[1].equals(error.toUpperCase())) {
				iErrorCode = 1;

				// Timeout
				if (timeOutCodes.indexOf(rspErrCd) > 0) {
					iErrorCode = 2;
				}
				// 업무에러코드에 없을 경우 통신(시스템)에러로 처리함
				else if (bizErrorCodes.indexOf(rspErrCd) == -1) {
					iErrorCode = 3;
				}
			}

			// 통계용 에러코드 설정
			msg.setStatErrorCode(iErrorCode);

			if (monitors == null)
				monitors = createMonitorVO();

			if (EAIMessageKeys.COMPLEX_PROCESS.equalsIgnoreCase(msg.getSvcPssTp())) {
				isSingle = false;
			}

			monitor = monitors.get(eaiSvcCd);
			// MonitorVO에 대한 Null check 후 새로 추가 로직 필요.
			if (monitor == null) {
				// EAIMessageManager에 있는지 확인 필요
				EAIMessage eaiMsg = eaiMsgManager.getEAIMessage(eaiSvcCd);

				if (eaiMsg != null) {
					monitor = new MonitorVO(eaiSvcCd);
					monitors.put(eaiSvcCd, monitor);
				} else {
					String errorText = ErrorCodeHandler.getMessage("RECEAICMT205");
					if (logger.isError())
						logger.error(ExceptionUtil.make("RECEAICMT205", errorText));
				}
			}

			if (monitor != null) {
				monitor.setIsSingle(isSingle);
				monitor.setBwkCls(bwkCls);

				if (msg.getGroupCoCd() == null || "".equals(msg.getGroupCoCd().trim()))
					monitor.setGroupCoCd("KB0"); // default : 은행(KB0)
				else
					monitor.setGroupCoCd(msg.getGroupCoCd());

				if (EAIMessageKeys.SYNC_SVC.equals(svcTsmtUsgTP) && EAIMessageKeys.SYNC_SVC.equals(psvItfTp)) {
					monitor.onEvent(IFType.SS, isSingle, logPssSno, msgPssTm, msgRcvTm, iErrorCode, svcOgNo, screnNo,
							intfacSendTranCd, adapterGroupName);
				} else if (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTP) && EAIMessageKeys.ASYNC_SVC.equals(psvItfTp)) {
					monitor.onEvent(IFType.AA, isSingle, logPssSno, msgPssTm, msgRcvTm, iErrorCode, svcOgNo, screnNo,
							intfacSendTranCd, adapterGroupName);
				} else if (EAIMessageKeys.ASYNC_SVC.equals(svcTsmtUsgTP) && EAIMessageKeys.SYNC_SVC.equals(psvItfTp)) {
					monitor.onEvent(IFType.AS, isSingle, logPssSno, msgPssTm, msgRcvTm, iErrorCode, svcOgNo, screnNo,
							intfacSendTranCd, adapterGroupName);
				} else {
					monitor.onEvent(IFType.SA, isSingle, logPssSno, msgPssTm, msgRcvTm, iErrorCode, svcOgNo, screnNo,
							intfacSendTranCd, adapterGroupName);
				}
			}
			
			////////////////////////////////////////////////////////////////////////////////////////////////////////////
			// 실시간 통계 로직 추가
			statisticsMonitor.recordStatistics(msg);
			////////////////////////////////////////////////////////////////////////////////////////////////////////////
			

			HashMap<String, MonitorVO> bwkVO = bwkClss.get(bwkCls);

			if (bwkVO != null) {
				bwkVO.put(eaiSvcCd, monitor);
				bwkClss.put(bwkCls, bwkVO);
			} else {
				bwkVO = new HashMap<>();
				bwkVO.put(eaiSvcCd, monitor);
				bwkClss.put(bwkCls, bwkVO);
			}
		} catch (Exception e) {
			String errorText = ErrorCodeHandler.getMessage("RECEAICMT204");
			if (logger.isError())
				logger.error(ExceptionUtil.make("RECEAICMT204", errorText));
		}
	}
	
	public void resetAll() {
		String[] keys = getAllMonitorVOKey();
		MonitorVO vo = null;

		for (int i = 0; i < keys.length; i++) {
			vo = monitors.get(keys[i]);
			if (vo != null) {
				vo.reset();
				vo.resetPeriod();
			}
		}
	}

	public void clearAll() {
		this.bwkClss.clear();
		this.monitors.clear();
	}

	public Iterator<MonitorVO> getAllMonitorVO() {
		return this.monitors.values().iterator();
	}

	public String[] getAllMonitorVOKey() {

		Iterator<String> it = this.monitors.keySet().iterator();

		ArrayList<String> keyList = new ArrayList<>();
		while (it.hasNext()) {
			String key = it.next();
			if (key != null) {
				keyList.add(key);
			}
		}

		String[] finalVOkey = keyList.toArray(new String[0]);

		if (finalVOkey.length > 0) {
			Arrays.sort(finalVOkey);
		}
		return finalVOkey;
	}

	public void removeMonitorVO(String eaiSvcCd) {
		monitors.remove(eaiSvcCd);
	}

	public MonitorVO getMonitorVO(String eaiSvcCd) {
		return monitors.get(eaiSvcCd);
	}

	public String[] getAllBwkClsKey() {
		Iterator<String> it = this.bwkClss.keySet().iterator();
		ArrayList<String> keyList = new ArrayList<>();
		while (it.hasNext()) {
			String key = it.next();
			if (key != null) {
				keyList.add(key);
			}
		}

		String[] finalVOkey = new String[keyList.size()];
		keyList.toArray(finalVOkey);
		if (finalVOkey.length > 0) {
			Arrays.sort(finalVOkey);
		}
		return finalVOkey;
	}

	public void removeBwkCls(String bwkCls) {
		bwkClss.remove(bwkCls);
	}

	public HashMap<String, MonitorVO> getBwkCls(String bwkCls) {
		return bwkClss.get(bwkCls);
	}

	private ConcurrentHashMap<String, MonitorVO> createMonitorVO() {
		ConcurrentHashMap<String, MonitorVO> monitorVOs = new ConcurrentHashMap<>();

		String date = DatetimeUtil.getCurrentDate();
		String wlServer = System.getProperty(Keys.SERVER_KEY);

		fileName = this.filePath + "/" + wlServer + "/MonitorVoData_" + date;
		if (logger.isDebug()) {
			logger.debug("EAIServiceMonitor ] fileName - [" + fileName + "]");
		}

		File rf = null;
		BufferedReader in = null;
		String msg = "";

		// file write
		// #eaiServiceCode/bwkCls/isSingle/ifType/groupCoCd: -- key
		// 100=2/200=2/300=2/400=2/900=2/9300=2/9400=2: -- 거래 count
		// 100=2/200=2/300=2/400=2/900=2/9300=2/9400=2/9900=2: -- error count
		// sumOfprocessTime/psvSumOfPssTime -- eai처리시간, 수동처리시간
		try {
			rf = new File(fileName);
			if (rf != null && rf.exists()) {
				in = new BufferedReader(new InputStreamReader(new FileInputStream(rf)));
				if (in != null) {
					MonitorVO vo = null;
					while ((msg = in.readLine()) != null) {
						if (logger.isDebug()) {
							logger.debug("EAIServiceMonitor ] createMonitorVO - msg[" + msg + "]");
						}

						if (msg.length() > 0) {
							String[] token = msg.split(master_delimiter);

							if (token.length != 4) {
								if (logger.isDebug()) {
									logger.warn("EAIServiceMonitor ] file data parsing error - " + token.length);
								}
								continue;
							} else {
								String[] key = token[0].split(sub_delimiter);
								String eaiSvcCd = key[0];
								String bwkCls = key[1];
								String groupCoCd = key[4]; // 그룹사코드 추가

								if (eaiSvcCd == null || eaiSvcCd.trim().length() == 0) {
									if (logger.isWarn()) {
										logger.warn("EAIServiceMonitor ] createMonitorVO - Skip Invalid eaiSvcCd - "
												+ eaiSvcCd);
									}
									continue;
								}
								vo = new MonitorVO(eaiSvcCd);

								if (vo == null) {
									if (logger.isWarn()) {
										logger.warn("EAIServiceMonitor ] createMonitorVO - monitorvo is null - "
												+ eaiSvcCd);
									}
									continue;
								}
								vo.setBwkCls(bwkCls);
								vo.setIfType(key[3]);
								vo.setGroupCoCd(groupCoCd);

								String[] pssTime = token[3].split(sub_delimiter);

								String pssTime0 = pssTime[0];
								String pssTime1 = pssTime[1];

								vo.setSumOfprocessTime(Double.parseDouble(pssTime0));
								vo.setPsvSumOfPssTime(Double.parseDouble(pssTime1));

								if ("true".equals(key[2])) { // 단일거래이면
									HashMap pssCount = vo.getPssCnt();
									HashMap errorCount = vo.getErrPssCnt();

									HashMap pssCountP = vo.getPssCntInPeriod(); // 최근시간
									HashMap errorCountP = vo.getErrPssCntInPeriod(); // 최근 시간

									String[] count = (token[1]).split(sub_delimiter);
									String[] error = (token[2]).split(sub_delimiter);

									for (int i = 0; i < count.length; i++) {
										String[] sub_count = count[i].split("=");
										pssCount.put(sub_count[0], sub_count[1]);
										pssCountP.put(sub_count[0], "0");
									}
									for (int i = 0; i < error.length; i++) {
										String[] sub_error = error[i].split("=");
										errorCount.put(sub_error[0], sub_error[1]);
										errorCountP.put(sub_error[0], "0");
									}
									vo.setPssCnt(pssCount);
									vo.setErrPssCnt(errorCount);
									vo.setPssCntInPeriod(pssCountP);
									vo.setErrPssCntInPeriod(errorCountP);

								} else { // 복합거래이면... 추가 로직 넣을것
									if (logger.isDebug()) {
										logger.debug("EAIServiceMonitor ] is not Single");
									}
								}
								if (logger.isDebug()) {
									logger.debug("EAIServiceMonitor ] Parsed MonitorVO : " + vo.toString());
								}
								monitorVOs.put(eaiSvcCd, vo);

								HashMap<String, MonitorVO> bwkVO = bwkClss.get(bwkCls);

								if (bwkVO != null) {
									MonitorVO mvo = bwkVO.get(eaiSvcCd);
									if (mvo == null) {

										bwkVO.put(eaiSvcCd, vo);
										bwkClss.put(bwkCls, bwkVO);
									}
								} else {
									bwkVO = new HashMap<>();
									bwkVO.put(eaiSvcCd, vo);
									bwkClss.put(bwkCls, bwkVO);
								}
							}
						}
					}
				}
			} else {
				if (logger.isWarn()) {
					logger.warn("EAIServiceMonitor ] File Not Found Skip Load File : " + fileName);
				}
			}
		} catch (Exception e) {
			if (logger.isWarn()) {
				logger.warn("Exception", e);
			}
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception ex) {
				if (logger.isWarn()) {
					logger.warn("close error", ex);
				}
			}
		}

		return monitorVOs;
	}

	public String getFilPath() {
		return this.filePath;
	}

	public void setFilePath(String path) {
		this.filePath = path;
	}

	public String getFilName() {
		return this.fileName;
	}

	public void setfileName(String name) {
		this.fileName = name;
	}

	public String getMasterDelimiter() {
		return this.master_delimiter;
	}

	public void setMasterDelimiter(String delimiter) {
		this.master_delimiter = delimiter;
	}

	public String getSubDelimiter() {
		return this.sub_delimiter;
	}

	public void setSubDelimiter(String delimiter) {
		this.sub_delimiter = delimiter;
	}

	public String resetErrorList() {
		PropManager pmanager = PropManager.getInstance();

		timeOutCodes = pmanager.getProperty(TO_ERRORLIST);
		bizErrorCodes = pmanager.getProperty(BIZ_ERRORLIST);

		// set current timeout error code list
		if (timeOutCodes == null || timeOutCodes.length() <= 0) {
			timeOutCodes = defTimeOutCodes;
		}

		if (logger.isWarn()) {
			logger.warn("\n\n\nEAIServiceMonitor] ==================================================================");
			logger.warn("EAIServiceMonitor] reset Timeout Error Code List >> " + timeOutCodes);
			logger.warn("EAIServiceMonitor] ==================================================================\n\n\n");
		}

		if (bizErrorCodes == null || bizErrorCodes.length() <= 0) {
			bizErrorCodes = defBizErrorCodes;
			if (logger.isWarn()) {
				logger.warn("EAIServiceMonitor] Biz Error Code List Property NOT SET Group[" + PROP_GROUP
						+ "] Property[" + BIZ_ERRORLIST + "]");
				logger.warn("EAIServiceMonitor] Set Default Value ...");
			}
		}

		if (logger.isWarn()) {
			logger.warn("\n\n\nEAIServiceMonitor] ==================================================================");
			logger.warn("EAIServiceMonitor] Biz Error Code List >> " + bizErrorCodes);
			logger.warn("EAIServiceMonitor] ==================================================================\n\n\n");
		}

		return "Reset Timeout Error Code List : [" + timeOutCodes + "] Biz Error Code List [" + bizErrorCodes + "]";
	}

	public String getMonitorDate() {
		return monitorDate;
	}

	public void setMonitorDate(String monitorDate) {
		this.monitorDate = monitorDate;
	}

	public boolean isTimeOutCodes(String errorCode) {
		if (timeOutCodes.indexOf(errorCode) >= 0) { // TIMEOUT일경우
			return true;
		}
		return false;
	}

	public boolean isBizErrorCodes(String errorCode) {
		if (bizErrorCodes.indexOf(errorCode) >= 0) { // biz 에러일 경우
			return true;
		}
		return false;
	}
}