package com.eactive.eai.rms.onl.server.handler;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.eactive.eai.common.monitor.MonitorVO;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.util.CommonUtil;
import com.eactive.eai.rms.onl.dashboard.service.Dashboard2RepositoryService;
import com.eactive.eai.rms.onl.server.repository.Repository;
import com.eactive.eai.rms.onl.server.repository.TransactionRepositoryService;
import com.eactive.eai.rms.onl.tracking.vo.MemStaticsVo;
import com.eactive.eai.rms.onl.vo.TransactionSendVo;
import com.eactive.eai.rms.onl.vo.TransactionTrackingVo;

@Component
public class TransactionSendHandler implements IMessageHandler {

    private static final Logger logger = Logger.getLogger(TransactionSendHandler.class);

    //private int timeToLive = 0;
    
    @Autowired
    @Qualifier("repository")
    private Repository repository;

    @Autowired
    @Qualifier("transactionRepositoryService")
    private TransactionRepositoryService transactionRepositoryService;
    
    
    @Autowired
    @Qualifier("dashboard2RepositoryService")
    private Dashboard2RepositoryService dashboard2Repository;
    
    
    private HashMap<String,Integer> mapProc = new HashMap<String,Integer>();
    private HashMap<String,Integer> mapError = new HashMap<String,Integer>();
    private HashMap<String,Integer> mapTimeout = new HashMap<String,Integer>();
    private HashMap<String,Integer> mapSerror = new HashMap<String,Integer>();
    
    private static final int EAISVC_TYPE_POSITION = 2;   //서비스코드 타입    R01 -> R  S01-> S
    
    
    public Class<TransactionSendVo> targetClass() {
        return TransactionSendVo.class;
    }

    public void messageReceived( Object message)
            throws Exception {
        TransactionSendVo vo = (TransactionSendVo) message; 

        if (logger.isDebugEnabled()) {
            logger.debug("RECV TransactionSendHandler] SEND DATA[HostName=" + vo.getHostName() + ", InstanceName=" + vo.getInstanceName() 
            	+ ", key1=" + vo.getKey1() + ", key2=" + vo.getKey2() + ", cmd=" +vo.getCmd()+"]");
        }
        // 호스트명, 인스턴스명을 초기화 한다.
        
        //DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getFirstDataSourceType());
		dashboard2Repository.initHostInstNames(false, null);
		dashboard2Repository.initEaiSevrDstcd(false);

        // 참고 : 지정된 호스트 이외의 데이터는 버린다.
		if( ! dashboard2Repository.isValidHost(vo.getHostName()) ) {
			logger.warn("invalid host name => " + vo.getHostName() );
			return ;
		}

        if ("END".equals(vo.getCmd())) { 
            // SendRepo 데이터 전체를 재계산 해서 
            // TransactionTrackingVo 를 생성 후 transactionRepository 에 
            // 저장한다.
        	
        	// F/W Agent 에서 key1 에 모니터링날짜(yyyyMMdd) 를 세팅하여 보내도록 수정함.
        	// 구버전과의 F/W Agent 와의 호환성을 고려하여 길이와 값을 체크한 후 사용함.
        	String time = vo.getKey1();
        	if( time != null && time.length() == 8 && "20".equals(time.substring(0,2)) ) {
        		// 오늘날짜가 아닌것은 bypass
        		if( ! time.equals(CommonUtil.getToday("yyyyMMdd")) ) {
        			return ;
        		}
        	}
        	
            calculateTrMemory(vo);

            calculateTrRepository(vo);
            
        } else {
            TransactionSendVo repo = (TransactionSendVo) repository.getMonitorDataNoExpire(
                vo.getHostName(), vo.getInstanceName(), vo.getCategory());
            if (repo == null) {
                repo = vo;
                repository.addMonitorDataNoExpire(repo);
            }
            if (logger.isDebugEnabled()){
            	logger.debug("setMapRepo vo.getKey1="+vo.getKey1() +",vo.getKey2="+vo.getKey2());
            }
            repo.setMapRepo(vo.getKey1(), vo.getKey2(), vo.getVo());            
        }
    }
    
    public void calculateTrMemory(TransactionSendVo recvVo) {
    	TransactionSendVo base = (TransactionSendVo)repository.getMonitorDataNoExpire(
    			recvVo.getHostName(), recvVo.getInstanceName(),
    			recvVo.getCategory());
    	
    	if(logger.isDebugEnabled()) {
    		logger.debug("calculateTrMemory : Repository for Transaction(host=" + recvVo.getHostName() + ", inst=" + recvVo.getInstanceName()
    		+ ", category=" + recvVo.getCategory() );
    	}
		
    	
    	if( base == null ) {
    		if(logger.isDebugEnabled()) {
	    		logger.debug("Repository for TransactionSendVo is Empty (host=" + recvVo.getHostName() + ", inst=" + recvVo.getInstanceName()
	    				+ ", category=" + recvVo.getCategory() );
    		}
    		return ;
    	}
    	
//    	HashMap<String,String> mapDstcd = dashboard2Repository.getRepoEAIServrDstcdByHost(recvVo.getHostName());
    	DataSourceType dataSourceType = dashboard2Repository.getServiceTypeByHost(recvVo.getHostName());
    	
    	if(logger.isDebugEnabled()) {
    		if(dataSourceType != null) { //취약점소스 수정 2020.08.25
    			logger.debug("dataSourceType="+dataSourceType.getName());
    		}
    	}
    	
    	MemStaticsVo total = new MemStaticsVo();
    	total.setHostName(recvVo.getHostName());
    	total.setInstName(recvVo.getInstanceName());
    	
    	HashMap<String, HashMap<String,MonitorVO>> all = base.getMapRepo();
    	Iterator<String> itBiz = all.keySet().iterator();
    	while( itBiz.hasNext() ) {
    		String bizKey = itBiz.next();
    		HashMap<String,MonitorVO> map = all.get(bizKey);
    		Iterator<String> itSvc = map.keySet().iterator();
    		while( itSvc.hasNext() ) {
    			String eaiSvcName  = itSvc.next();
    			MonitorVO fwVo     = map.get(eaiSvcName);
    			MemStaticsVo memVo = null;
    			 if(dataSourceType != null) { //취약점소스 수정 2020.08.25
    				 memVo = convertMemVo(fwVo, dataSourceType, total.getHostName(), total.getInstName());
    			 }
    			
    			total.add(memVo);
    		}
    	}
    	dashboard2Repository.setMemTradeVo(recvVo.getHostName(), recvVo.getInstanceName(), total);
    }
    
    public MemStaticsVo convertMemVo(MonitorVO mVo, DataSourceType dataSourceType, String host, String inst) {
    	MemStaticsVo vo = new MemStaticsVo();
    	
    	String eaiSvcName = mVo.getEaiServiceCode();
    	int    pos        = MemStaticsVo.getPos(dataSourceType);
    	if( pos < 0 ) {
    		return vo; // empty vo
    	}
    	
        String[] pssCntKey    = mVo.getAllPssCntKey();
        String[] errPssCntKey = mVo.getAllErrPssCntKey();
        HashMap pssCnt        = mVo.getPssCnt();
        HashMap errPssCnt     = mVo.getErrPssCnt();
        
        if (pssCntKey != null && pssCntKey.length > 3
                && errPssCntKey != null && errPssCntKey.length > 7) {
        	int p100 = Integer.parseInt((String) pssCnt.get(pssCntKey[0])); 
        	int p200 = Integer.parseInt((String) pssCnt.get(pssCntKey[1])); 
        	int p300 = Integer.parseInt((String) pssCnt.get(pssCntKey[2])); 
        	int p400 = Integer.parseInt((String) pssCnt.get(pssCntKey[3]));
        	
        	int e100 = new Integer(errPssCnt.get(errPssCntKey[0]).toString());
        	int e200 = new Integer(errPssCnt.get(errPssCntKey[1]).toString());
        	int e300 = new Integer(errPssCnt.get(errPssCntKey[2]).toString());
        	int e400 = new Integer(errPssCnt.get(errPssCntKey[3]).toString());
        	int e900 = new Integer(errPssCnt.get(errPssCntKey[4]).toString());

        	int e9300 = new Integer(errPssCnt.get(errPssCntKey[5]).toString());
        	int e9400 = new Integer(errPssCnt.get(errPssCntKey[6]).toString());
        	int e9900 = new Integer(errPssCnt.get(errPssCntKey[7]).toString());
        	
        	//SystemError
        	//int s100 = new Integer(errPssCnt.get(errPssCntKey[8]).toString());
        	//int s200 = new Integer(errPssCnt.get(errPssCntKey[9]).toString());
        	//int s300 = new Integer(errPssCnt.get(errPssCntKey[10]).toString());
        	int s400 = new Integer(errPssCnt.get(errPssCntKey[11]).toString());
        	int s900 = new Integer(errPssCnt.get(errPssCntKey[12]).toString());
        	
        	
        	
        	String ifType = mVo.getIfType();
        	
        	int total = 0 ;
        	int error = 0 ;
        	int timeout = 0 ;
        	int proc   = 0 ;
        	
        	int serror = 0 ;
        	
        	char RType = ' ' ;
        	if( eaiSvcName != null && eaiSvcName.length() > EAISVC_TYPE_POSITION ) {
        		RType = eaiSvcName.charAt(eaiSvcName.length()- EAISVC_TYPE_POSITION);        		
        	}

        	if( "SA".equals(ifType) ) {
        		// SA 타입의 응답거래는 건수계산에서 제외한다.
        		if( RType == 'R' || RType == 'r' ) {
        			return vo;
        		}
        	} 
        	
        	if("AA".equalsIgnoreCase(mVo.getIfType())) {
        		
        		// TODO : 전체건수 계산식을 수정하여 테스트 한다. : 2010.01.19 ( dhlee )
        		//        e900  에만 건수가 있는 case 는 총건수가 음수로 나오는데, 보정이 필요하다.
        		if( RType == 'S' || RType == 's' ) {
        			total = p100 + e100 ;
        		} else { // R,r
        			total = p300 + e300 ;
        		}
        		
        		error   = e900;
        		serror  = s900;  
        		timeout = e9900;

        		proc    = total - ( error + timeout );
        		
        		//업무에러 = 업무에러 - 통신에러 20201011 수정
        		error = error - serror ; 
        		
        		// TODO : 정상건수가 0보다 작을 가능성 이 있는지 확인할것.
        		if( proc < 0 ) {
        			if( logger.isDebugEnabled() ) {
            			logger.debug("proc 값이 0 보다 작음 : [" + eaiSvcName + "," + RType + "] proc=" + proc + ", total=" + total + ", error=" + error + ", timeout=" + timeout + 
				                 "P(" + p100 + "," + p200 + "," + p300 + "," + p400 + ")  E(" + e100 + "," + e200 + "," + e300 + "," + e400 +
				                 ")  T(" + e9300 + "," + e9400 + "," + e9900 + ")" );        				
        			}
        			
        			// 참고 : 화면 의 에러건수 에서 Sync 가 맞지 않는 에러 때문에 블럭.
        			//total -= proc ;
        			//proc  -= proc ;
        		}
        	} else {
        		total   = p100 + e100;
        		error   = e400 + e900 ;
        		serror  = s400 + s900 ; 
        		timeout = e9400;
        		proc    = total - ( error + timeout ) ;
        		
        		//업무에러 = 업무에러 - 통신에러 20201011 수정
        		error = error - serror ; 
        	}
        	
        	// 900 에러만 발생한 경우에 대한 보정
        	if( proc < 0 ) {
        		total = total - proc;
        		proc  = 0 ;
        	}
        	
        	
        	
        	if( logger.isDebugEnabled() ) {
            	String testKey = host + "." + inst + "." + eaiSvcName ;
            	int p1=0, t1=0, e1=0 ,s1 =0 ;
            	Integer p = mapProc.get(testKey);
            	Integer t = mapTimeout.get(testKey);
            	Integer e = mapError.get(testKey);
            	Integer s = mapSerror.get(testKey);
            	if( p != null ) p1 = p;
            	if( t != null ) t1 = t;
            	if( e != null ) e1 = e;
            	if( s != null ) s1 = s;

            	if( proc < p1 ) {
            		logger.debug(host + "," + inst + "," +  eaiSvcName + " $$$ proc 값이 이전보다 작습니다. (old=" + p1 + ", new=" + proc + ")" );
            	}
            	if( timeout < t1 ) {
            		logger.debug(host + "," + inst + "," +  eaiSvcName + " $$$ timeout 값이 이전보다 작습니다. (old=" + t1 + ", new=" + timeout + ")" );
            	}
            	if( error < e1 ) {
            		logger.debug(host + "," + inst + "," +  eaiSvcName + " $$$ error 값이 이전보다 작습니다. (old=" + e1 + ", new=" + error + ")" );
            	}  
            	if( serror < s1 ) {
            		logger.debug(host + "," + inst + "," +  eaiSvcName + " $$$ serror 값이 이전보다 작습니다. (old=" + s1 + ", new=" + serror + ")" );
            	}  

            	// 20200622 : 거래처리건수를 전체건수로 변경
//            	mapProc.put(testKey, proc);
            	mapProc.put(testKey, total);
            	mapTimeout.put(testKey, timeout);
            	mapError.put(testKey, error);
            	mapSerror.put(testKey, serror); //SystemError 추가
        	}
        	
        	// 20200622 : 거래처리건수를 전체건수로 변경
//    		vo.setProc(pos, proc);
    		vo.setProc(pos, total);
    		vo.setError(pos, error);
    		vo.setTimeout(pos, timeout);
    		vo.setSerror(pos, serror);//SystemError 추가
        }
    	return vo;
    }

    public void calculateTrRepository(TransactionSendVo recvVo) {
        
        TransactionSendVo base = (TransactionSendVo) repository.getMonitorDataNoExpire(
            recvVo.getHostName(), recvVo.getInstanceName(),
            recvVo.getCategory());
        if( base == null ) {
        	if( logger.isDebugEnabled() ) {
	            logger.debug( "Repository for TransactionSendVo is Empty (host=" + recvVo.getHostName() + ", inst=" + recvVo.getInstanceName()
	    				+ ", category=" + recvVo.getCategory() );
        	}
    		return ;
        }
        
        TransactionTrackingVo totalVo = new TransactionTrackingVo();
        totalVo.setDate( new Date());
        totalVo.setHostName( recvVo.getHostName());
        totalVo.setInstanceName( recvVo.getInstanceName());
        
        
        HashMap<String, HashMap<String,MonitorVO>> all = base.getMapRepo();
        
        Iterator<String> it1 = all.keySet().iterator();
        while( it1.hasNext() ) {
            String key1 = it1.next();
            HashMap<String,MonitorVO> map = all.get(key1);
            
            // sum count for dashboard
            addCountByBwk(totalVo, map);

            // recent 10 minutes, total transaction data
            HashMap<String, TransactionTrackingVo> mapRecent = convertMonitorVO(
                map, true);
            totalVo.appendMapRecent(key1,
                mapRecent);

            // today, total transaction data
            HashMap<String, TransactionTrackingVo> mapToday = convertMonitorVO(
                map, false);
            totalVo.appendMapToday(key1, mapToday);            
        }
        

        TransactionTrackingVo todayVo = transactionRepositoryService.getTrackingVo(totalVo);
        
        receiveProcess( totalVo, todayVo );
    }

    private void receiveProcess( TransactionTrackingVo recvVo, TransactionTrackingVo toDayVo ) {
        /*
         * 
         */
        if (toDayVo == null) {
            toDayVo = recvVo;
        }

        if (logger.isDebugEnabled()) {
            logger.debug("** RECV Transaction data["
                    + recvVo.getInstanceName() + "] biz="
                    + recvVo.getBizCode() + ", proc100="
                    + recvVo.getProc100());
        }

        
        // FIXME : 2009.08.25 YUN 신대시보드가 완성되면, 전일 거래건수는 메모리에서 구하지 않고,
        /**
         * DB 에서 구하게 된다.
         * 따라서 아래의 로직은 필요 없게 되므로, 
         * 아래의 로직을 확인 후 , 삭제하고
         * 현재 메모리의 날짜와, 수신받은 데이터의 날짜가 다른 경우, 메모리 맵 데이터를
         * 모두 삭제처리 함으로써 Gabage 레코드가 남지 않도록 한다.
         */
        
        
        /*
         * 수신 받은 vo가 어제 날짜의 vo라면 vo의 날짜갱신과 전일 총 거래 건수, 전일 총 에러 건수를 백업 한다.
         */
        if (!DateUtils.isSameDay(toDayVo.getDate(), recvVo.getDate())) {
            toDayVo.setTotalProcAllYesterday(toDayVo.getTotalProcAll());
            toDayVo.setTotalProcYesterday(toDayVo.getTotalProc());
            toDayVo.setTotalErrorYesterday(toDayVo.getTotalError());
            toDayVo.setTotalTimeoutYesterday(toDayVo.getTotalTimeout());
            toDayVo.setDate(recvVo.getDate());
        }

        if (toDayVo.getTps() < recvVo.getTps()) {
            toDayVo.setTps(recvVo.getTps());
        }

        toDayVo.setError100(recvVo.getError100());
        toDayVo.setError200(recvVo.getError200());
        toDayVo.setError300(recvVo.getError300());
        toDayVo.setError400(recvVo.getError400());
        toDayVo.setError900(recvVo.getError900());

        toDayVo.setError9300(recvVo.getError9300());
        toDayVo.setError9400(recvVo.getError9400());
        toDayVo.setError9900(recvVo.getError9900());

        toDayVo.setProc100(recvVo.getProc100());
        toDayVo.setProc200(recvVo.getProc200());
        toDayVo.setProc300(recvVo.getProc300());
        toDayVo.setProc400(recvVo.getProc400());

        toDayVo.setMapRecent(recvVo.getMapRecent()); // all 10 min data of instance
        toDayVo.setMapToday(recvVo.getMapToday()); // all today data of instance

        toDayVo.setTotalProcAll(recvVo.getTotalProcAll());
        toDayVo.setTotalProc(recvVo.getTotalProc());
        toDayVo.setTotalError(recvVo.getTotalError());
        toDayVo.setTotalTimeout(recvVo.getTotalTimeout());

        toDayVo.setCategory(recvVo.getCategory());
        toDayVo.setHostName(recvVo.getHostName());
        toDayVo.setInstanceName(recvVo.getInstanceName());

        transactionRepositoryService.setTrackingVo(toDayVo);        
    }
    
    
    /**
     * rms_client 의 TransactionTrackingAgent 에 있는 함수와 동일하다.
     * 차후 테스트 가 완료 되면, rms_client 에 있는 함수는 삭제할것.
     * @param totalVo
     * @param voByBwk
     */
    private void addCountByBwk(TransactionTrackingVo totalVo,
            HashMap<String, MonitorVO> voByBwk) {
    	
    	
        for (MonitorVO frameworkMonitorVo : voByBwk.values()) {
            String[] pssCntKey = frameworkMonitorVo.getAllPssCntKey();
            String[] errPssCntKey = frameworkMonitorVo.getAllErrPssCntKey();
            HashMap pssCnt = frameworkMonitorVo.getPssCnt();
            HashMap errPssCnt = frameworkMonitorVo.getErrPssCnt();

            if (pssCntKey != null && pssCntKey.length > 3
                    && errPssCntKey != null && errPssCntKey.length > 7) {

                // 원래 서버에서의 코드는 getBean() 으로 얻던 부분임
                TransactionTrackingVo currentVo = new TransactionTrackingVo();
                currentVo.setHostName(totalVo.getHostName());
                currentVo.setInstanceName(totalVo.getInstanceName());

                currentVo.setProc100(Integer.parseInt((String) pssCnt.get(pssCntKey[0])));
                currentVo.setProc200(Integer.parseInt((String) pssCnt.get(pssCntKey[1])));
                currentVo.setProc300(Integer.parseInt((String) pssCnt.get(pssCntKey[2])));
                currentVo.setProc400(Integer.parseInt((String) pssCnt.get(pssCntKey[3])));

                currentVo.setError100(new Integer(
                        errPssCnt.get(errPssCntKey[0]).toString()));
                currentVo.setError200(new Integer(
                        errPssCnt.get(errPssCntKey[1]).toString()));
                currentVo.setError300(new Integer(
                        errPssCnt.get(errPssCntKey[2]).toString()));
                currentVo.setError400(new Integer(
                        errPssCnt.get(errPssCntKey[3]).toString()));

                currentVo.setError900(new Integer(
                        errPssCnt.get(errPssCntKey[4]).toString()));

                // timeout error                
                currentVo.setError9300(new Integer(errPssCnt.get(
                    errPssCntKey[5]).toString()));
                currentVo.setError9400(new Integer(errPssCnt.get(
                    errPssCntKey[6]).toString()));
                currentVo.setError9900(new Integer(errPssCnt.get(
                    errPssCntKey[7]).toString()));

                addCount(totalVo, currentVo);

                addTotal(totalVo, frameworkMonitorVo, currentVo);

                addTps(totalVo, frameworkMonitorVo, currentVo);
            }
        }
    }
    
    /**
     * Convert the MonitorVO map to TransactionTrackingVo map.
     * 
     * @param totalVo the data vo
     * @param voByBwk the vo by bwk
     */
    @SuppressWarnings("unchecked")
    private HashMap<String, TransactionTrackingVo> convertMonitorVO(
            HashMap<String, MonitorVO> mapMonitor, boolean recent) {

        HashMap<String, TransactionTrackingVo> mapTrans = new HashMap<String, TransactionTrackingVo>();

        Iterator it = mapMonitor.keySet().iterator();
        String[] keys = new String[mapMonitor.size()];
        for (int i = 0; it.hasNext(); i++) {
            keys[i] = (String) it.next();
        }

        for (int i = 0; i < keys.length; i++) {
            MonitorVO monitor = mapMonitor.get(keys[i]);

            String[] pssKey = monitor.getAllPssCntKey(); // 4 proc
            HashMap pssCnt = monitor.getPssCnt();
            HashMap pssRecent = monitor.getPssCntInPeriod();

            String[] errKey = monitor.getAllErrPssCntKey(); // 8 error
            HashMap errCnt = monitor.getErrPssCnt();
            HashMap errRecent = monitor.getErrPssCntInPeriod();

            if (pssKey.length > 3 && errKey.length > 7) {
                TransactionTrackingVo currentVo = new TransactionTrackingVo();
                currentVo.setEaiServiceCode(keys[i]);
                currentVo.setIfType(monitor.getIfType());

                double dAvg = 0;
                double dPsvAvg = 0;
                double dAvg2 = 0;
                double dPsvAvg2 = 0;
                int cnt400 = 0;
                double eaiProcTime = 0;

                if (recent && pssRecent != null && errRecent != null) { // 최근 10분
                    currentVo.setProc100(new Integer(pssRecent.get(pssKey[0])
                            .toString()));
                    currentVo.setProc200(new Integer(pssRecent.get(pssKey[1])
                            .toString()));
                    currentVo.setProc300(new Integer(pssRecent.get(pssKey[2])
                            .toString()));
                    currentVo.setProc400(new Integer(pssRecent.get(pssKey[3])
                            .toString()));

                    currentVo.setError100(new Integer(errRecent.get(errKey[0])
                            .toString()));
                    currentVo.setError200(new Integer(errRecent.get(errKey[1])
                            .toString()));
                    currentVo.setError300(new Integer(errRecent.get(errKey[2])
                            .toString()));
                    currentVo.setError400(new Integer(errRecent.get(errKey[3])
                            .toString()));
                    currentVo.setError900(new Integer(errRecent.get(errKey[4])
                            .toString()));

                    // timeout error
                    currentVo.setError9300(new Integer(errRecent.get(errKey[5])
                            .toString()));
                    currentVo.setError9400(new Integer(errRecent.get(errKey[6])
                            .toString()));
                    currentVo.setError9900(new Integer(errRecent.get(errKey[7])
                            .toString()));

                    dAvg2 = monitor.getSumOfProcessTimeInPeriod();
                    dPsvAvg2 = monitor.getPsvSumOfPssTimeInPeriod();
                } else if (!recent && pssCnt != null && errCnt != null) { // 오늘
                    currentVo.setProc100(new Integer(pssCnt.get(pssKey[0])
                            .toString()));
                    currentVo.setProc200(new Integer(pssCnt.get(pssKey[1])
                            .toString()));
                    currentVo.setProc300(new Integer(pssCnt.get(pssKey[2])
                            .toString()));
                    currentVo.setProc400(new Integer(pssCnt.get(pssKey[3])
                            .toString()));

                    currentVo.setError100(new Integer(errCnt.get(errKey[0])
                            .toString()));
                    currentVo.setError200(new Integer(errCnt.get(errKey[1])
                            .toString()));
                    currentVo.setError300(new Integer(errCnt.get(errKey[2])
                            .toString()));
                    currentVo.setError400(new Integer(errCnt.get(errKey[3])
                            .toString()));
                    currentVo.setError900(new Integer(errCnt.get(errKey[4])
                            .toString()));

                    // timeout error
                    currentVo.setError9300(new Integer(errCnt.get(errKey[5])
                            .toString()));
                    currentVo.setError9400(new Integer(errCnt.get(errKey[6])
                            .toString()));
                    currentVo.setError9900(new Integer(errCnt.get(errKey[7])
                            .toString()));

                    dAvg2 = monitor.getSumOfprocessTime();
                    dPsvAvg2 = monitor.getPsvSumOfPssTime();

                    if (logger.isDebugEnabled()) {
                        StringBuffer sb = new StringBuffer();
                        sb.append("RMS_TR_ORIGIN:key=");
                        sb.append(keys[i]);
                        sb.append(" IfType=");
                        sb.append(monitor.getIfType());
                        sb.append(" proc=");
                        for (int x = 0; x < 4; x++) {
                            sb.append(pssCnt.get(pssKey[x]).toString());
                            sb.append(",");
                        }
                        sb.append(" err=");
                        for (int x = 0; x < 8; x++) {
                            sb.append(errCnt.get(errKey[x]).toString());
                            sb.append(",");
                        }
                        logger.debug(sb.toString());
                    }
                }

                cnt400 = currentVo.getProc400();

                if ("AA".equalsIgnoreCase(monitor.getIfType())) {
                    if (dAvg2 > 0 && currentVo.getProc200() > 0) {
                        dAvg = dAvg2 / currentVo.getProc200() / 1000;
                    }
                    if (dAvg2 > 0 && currentVo.getProc400() > 0) {
                        dAvg = dAvg2 / currentVo.getProc400() / 1000;
                    }
                } else {
                    if (dAvg2 > 0 && currentVo.getProc400() > 0) {
                        dAvg = dAvg2 / currentVo.getProc400() / 1000;
                    }
                }

                if (dPsvAvg2 > 0 && currentVo.getProc300() > 0) {
                    if (monitor.getIsSingle()) { // 단일 거래의 경우 
                        dPsvAvg = dPsvAvg2 / currentVo.getProc300() / 1000;
                    } else { // 복합거래의 경우 
                        dPsvAvg = dPsvAvg2 / currentVo.getProc100() / 1000;
                    }
                }

                eaiProcTime = dAvg - dPsvAvg;
                if ( eaiProcTime < 0 )
                    eaiProcTime = 0;

                currentVo.setTimeEai(eaiProcTime);
                currentVo.setTimePsv(dPsvAvg);
                currentVo.setTimeTotal(dAvg);
                if (dAvg != 0)
                    currentVo.setTps(cnt400 / dAvg);

                mapTrans.put(keys[i], currentVo);
            }
        }

        return mapTrans;
    }

    private void addTotal(TransactionTrackingVo totalVo,
            MonitorVO frameworkMonitorVo, TransactionTrackingVo currentVo) {

        currentVo.setIfType(frameworkMonitorVo.getIfType());
        currentVo.calcTotalCount();

        totalVo.addTotalProcAll(currentVo.getTotalProcAll());
        totalVo.addTotalProc(currentVo.getTotalProc());
        totalVo.addTotalError(currentVo.getTotalError());
        totalVo.addTotalTimeout(currentVo.getTotalTimeout());
    }

    /**
     * Adds the tps.
     * 
     * @param totalVo the data vo
     * @param frameworkMonitorVo the framework monitor vo
     * @param pssCntKey the pss cnt key
     * @param pssCnt the pss cnt
     */
    private void addTps(TransactionTrackingVo totalVo,
            MonitorVO frameworkMonitorVo, TransactionTrackingVo currentVo) {

        double totalProcTimeAvg = 0;
        double sumOfProcessTime = frameworkMonitorVo.getSumOfprocessTime();

        double psvProcTimeAvg = 0;
        double psvSumOfPssTime = frameworkMonitorVo.getPsvSumOfPssTime();
        double tps = 0;

        if ("AA".equalsIgnoreCase(frameworkMonitorVo.getIfType())
                && (sumOfProcessTime > 0) && (currentVo.getProc200() > 0)) {
            /*
             * A-A 거래이고 200 값이 0보다 클 경우 
             */
            totalProcTimeAvg = sumOfProcessTime / currentVo.getProc200() / 1000;
        }

        if ((sumOfProcessTime > 0) && (currentVo.getProc400() > 0)) {
            totalProcTimeAvg = sumOfProcessTime / currentVo.getProc400() / 1000;
        }

        if ((psvSumOfPssTime > 0) && (currentVo.getProc300() > 0)) {

            if (frameworkMonitorVo.getIsSingle()) {
                // 단일 거래의 경우
                psvProcTimeAvg = psvSumOfPssTime / currentVo.getProc300()
                        / 1000;
            } else {
                // 복합거래의 경우
                psvProcTimeAvg = psvSumOfPssTime / currentVo.getProc100()
                        / 1000;
            }
        }

        double eaiProcTime = totalProcTimeAvg - psvProcTimeAvg;

        if (eaiProcTime < 0) {
            eaiProcTime = 0;
        }

        if ("AA".equalsIgnoreCase(frameworkMonitorVo.getIfType())
                && eaiProcTime > 0) {
            /*
             * A-A 거래의 경우 TPS = 총 거래 건수 / eaiProcTime 
             */
            if (currentVo.getProc200() > 0) {
                tps = currentVo.getProc200() / eaiProcTime;
            } else {
                tps = currentVo.getProc400() / eaiProcTime;
            }
        } else {
            /*
             * A-A 거래가 아닌 경우 TPS = 거래 건수 / 평균처리시간
             */
            tps = currentVo.getProc400() / totalProcTimeAvg;
        }

        /*
         * NaN : proc400, dAvg 모두 0일 경우
         * Infinite : dAvg 값은 있으나 proc 값이 없을 경우 
         */
        if (Double.isNaN(tps) || Double.isInfinite(tps)) {
            tps = 0;
        }

        totalVo.addTps(tps);
    }

    /**
     * Adds the count.
     * 
     * @param totalVo the total vo
     * @param currentVo the current vo
     */
    private void addCount(TransactionTrackingVo totalVo,
            TransactionTrackingVo currentVo) {
        totalVo.addProc100(currentVo.getProc100());
        totalVo.addProc200(currentVo.getProc200());
        totalVo.addProc300(currentVo.getProc300());
        totalVo.addProc400(currentVo.getProc400());

        totalVo.addError100(currentVo.getError100());
        totalVo.addError200(currentVo.getError200());
        totalVo.addError300(currentVo.getError300());
        totalVo.addError400(currentVo.getError400());
        totalVo.addError900(currentVo.getError900());

        totalVo.addError9300(currentVo.getError9300());
        totalVo.addError9400(currentVo.getError9400());
        totalVo.addError9900(currentVo.getError9900());
    }    
}
