package com.eactive.eai.rms.onl.manage.rule.upload;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.eactive.eai.adapter.socket2.common.StopWatch;
import com.eactive.eai.agent.command.CommonCommand;
import com.eactive.eai.common.util.DatetimeUtil;
import com.eactive.eai.common.util.SystemUtil;
import com.eactive.eai.rms.common.base.OnlBaseAnnotationController;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
import com.eactive.eai.rms.common.interceptor.dynamicLog.DynamicLogController;
import com.eactive.eai.rms.common.util.ItsmSmsSender;
import com.eactive.eai.rms.onl.common.exception.BizException;

@Controller 
public class IoMapLoaderController extends OnlBaseAnnotationController implements InterceptorSkipController, IoMapLoaderKey, DynamicLogController {

    private static final Logger logger = Logger.getLogger("DYNAMIC_LOGGER");
    
	@Autowired
	@Qualifier("monitoringContext")
	private MonitoringContext monitoringContext;
    
    @Autowired
    @Qualifier("ioMapLoaderService") 
    private IoMapLoaderService service; 
    
    @Autowired
    @Qualifier("ioMapLoaderForMonitoringService") 
    private IoMapLoaderForMonitoringService serviceMonitoring; 
 

    /**
     * iocm 호출 관련 컨트롤러
     * 형상 관리에서 호출(iocm.sh)
     * /usr/java5/bin/java -classpath $CP_ARGS -DItsmPermIP=172.17.161.88 -DItsmPermPORT=3264 com.kbstar.eai.common.loader.IOMapLoader_312 $APP_CONF/config/ 99991231 $1 $2 $3 $4  >> $LOGFILE
     * 1. 긴급CM 은 TSEAIIL01에 패키지 등록 , 형상대상 DB 적재및 동기화
     * 2. 일자전환,IPL,예약 CM은 TSEAIIL01에 패키지 등록 만
     * 
     * ex) $APP_CONF/config/ 99991231 $1 $2 $3 $4
     *     config(고정) 영업일자(고정) 업무코드 패키지번호 실행시간 일자전환속성(Y/P/N)
     * @param request
     * @param response
     * @param schema
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=iocm"})
    public ModelAndView iocm(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	
    	Properties prop = monitoringContext.getProperties();
		
		String downloadPath   = prop.getProperty(MonitoringContext.CM_IOMAP_PATH, "/fscm/iomap/");

    	if (SystemUtil.isDevServer()){
    		HashMap<String,Object> result = new HashMap<String,Object>();
    		result.put("status","fail");
    		result.put("errorCode","999");
    		result.put("errorMsg","not support dev server");
            return new ModelAndView("jsonView", result );
    	}
		//String configPath = request.getParameter(CONFIGPATH); // Config File Path //1번 파라미터  <=== DB정보, TOBE에서는 사용하지 않음
		//String workDay    = request.getParameter(WORKDAY);    // 영업일자                   //2번 파라미터  <==영업일자는 일자전환에서만 사용
		String apCode     = request.getParameter(APCODE);     // 업무코드                   //3번 파라미터
		String pkgNumber  = request.getParameter(PKGNUMBER);  // 패키지번호                //4번 파라미터
		String runTime    = request.getParameter(RUNTIME);    // 실행시간                   //5번 파라미터
		String midNight   = request.getParameter(MIDNIGHT);   // 일자전환속성 Y/P/N  //6번 파라미터
		String currentTime = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(ZonedDateTime.now());
		
		//cm 종류 확인
		String cmKind ="";
		if ("Y".equals(midNight)){ //일자전환 CM
			cmKind = CM_MIDNIGHT;
		}else if ("P".equals(midNight)){ //IPL CM
			cmKind = CM_IPL;
		}else if ("N".equals(midNight) && Long.parseLong(currentTime) < Long.parseLong(runTime) ){//예약 CM
			cmKind = CM_RESERV;
		}else if ("N".equals(midNight) && Long.parseLong(currentTime) >= Long.parseLong(runTime) ){//긴급 CM
			cmKind = CM_EMERGENCY;
		}
		boolean status    = true;
		String errorCode  = "000";
		String applyYn    = "N";

		StopWatch sw = new StopWatch();
		sw.start();
		
		if (CM_MIDNIGHT.equals(cmKind) || CM_IPL.equals(cmKind) || CM_RESERV.equals(cmKind)){
			applyYn = "N";
		}else if (CM_EMERGENCY.equals(cmKind)){
			applyYn = "Y";
			logger.info("긴급 CM이 시작 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다." );
			//1.CM 대상 파일 존재 여부(001)
			//2.IL02 저장 및 인터페이스 존재여부 check
			//3.CM 대상 파일 DB적재
			//4.CM 대상 파일 메모리 동기화
			errorCode = fileCheckAndDbInsertAndSync(downloadPath, apCode, pkgNumber);
			if (!"000".equals(errorCode)){
				status = false;
			}
			logger.info("긴급 CM이 시작 종료 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. errorCode " + errorCode);
		}
		//il01 등록
		//il01 등록 오류시  applyYn은 Y로 설정한다.
		serviceMonitoring.loadTSEAIRM29(apCode, pkgNumber, runTime, midNight, applyYn,errorCode,cmKind);
		sw.stop();
		if (status){
			logger.info("CM PACKAGE NUMBER : "+pkgNumber +" CM KIND "+cmKind+" CM으로 등록 완료되었습니다. 수행시간 : " + sw.toString());
		}else{
			logger.info("CM PACKAGE NUMBER : "+pkgNumber +" CM KIND "+cmKind+" CM 실패 하였습니다. errorCode = " + errorCode + " 수행시간 : " + sw.toString());
			smsSend(pkgNumber,getMessage(errorCode));
		}
		HashMap<String,Object> result = new HashMap<String,Object>();
		result.put("status",status?"success":"fail");
		result.put("errorCode",errorCode);
		result.put("errorMsg",getMessage(errorCode));
        return new ModelAndView("jsonView", result );
   

    }
    /**
     * 예약 CM만 호출됨
     * CRON TAB 에서 호출(cron.sh)
     * /usr/java5/bin/java -classpath $CP_ARGS -DItsmPermIP=172.17.161.88 -DItsmPermPORT=3264 com.kbstar.eai.common.loader.IOMapCronTab $APP_CONF/config/ >> $LOGFILE
     * ex) $APP_CONF/config/
     *     config(고정)
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=cron"})
    public ModelAndView cron(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	Properties prop = monitoringContext.getProperties();
		
    	String downloadPath   = prop.getProperty(MonitoringContext.CM_IOMAP_PATH, "/fscm/iomap/");

    	if (SystemUtil.isDevServer()){
    		HashMap<String,Object> result = new HashMap<String,Object>();
    		result.put("status","fail");
    		result.put("errorCode","999");
    		result.put("errorMsg","not support dev server");
            return new ModelAndView("jsonView", result );
    	}
		//String configPath = request.getParameter(CONFIGPATH); // Config File Path //1번 파라미터  <=== DB정보, TOBE에서는 사용하지 않음
		//String workDay    = request.getParameter(WORKDAY);    // 영업일자                   //2번 파라미터  <==영업일자는 일자전환에서만 사용
		String apCode     = ""; // 업무코드                   //3번 파라미터
		String pkgNumber  = ""; // 패키지번호                //4번 파라미터
		String runTime    = ""; // 실행시간                   //5번 파라미터
		String midNight   = ""; // 일자전환속성 Y/P/N  //6번 파라미터
		String currentTime = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(ZonedDateTime.now());
		
		boolean status    = true;
		String errorCode  = "000";
		List<HashMap> list = serviceMonitoring.selectTSEAIRM29("N","N");
		if (list == null || list.size()==0){
			logger.info("예약 CM DB에  대상 데이터가 없습니다." );
		}else{
			for(HashMap row : list){
				status = true;
				errorCode = "000";
				apCode    = ((String)row.get("EAIBZWKDSTCD")).trim();     //업무구분코드
				pkgNumber = ((String)row.get("MODFIMGTPCKAGNO")).trim();  //패키지번호
				runTime   = ((String)row.get("MODFIMGTMODFIYMS")).trim(); //실행일자
				midNight  = ((String)row.get("DTECNVSNYN")).trim();       //일자전환여부
				if ( "N".equals(midNight) && ( Long.parseLong(currentTime) > Long.parseLong(runTime) ) ) {
					StopWatch sw = new StopWatch();
					try{
						logger.info("예약 CM이 시작 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다." );
						sw.start();
						//1.CM 대상 파일 존재 여부(001)
						//2.IL02 저장 및 인터페이스 존재여부 check
						//3.CM 대상 파일 DB적재
						//4.CM 대상 파일 메모리 동기화
						errorCode = fileCheckAndDbInsertAndSync(downloadPath, apCode, pkgNumber);
						if (!"000".equals(errorCode)){
							status = false;
						}
						sw.stop();
						logger.info("예약 CM이 완료 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString());
						//il01 update //정상이든 오류든 EAI 적용여부는 Y
						serviceMonitoring.updateTSEAIRM29(pkgNumber, midNight, "Y", errorCode);
					}catch(Exception e){
						smsSend(pkgNumber,"예약 CM이 오류가 발생");
						logger.error("예약 CM이 오류가 발생 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString(),e);
					}finally{
						if (!status){
							smsSend(pkgNumber,getMessage(errorCode));
							logger.error("예약 CM이 오류가 발생 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString());
							//초기화
							status=true;
							errorCode="000";
						}
					}
				}else{
					logger.info("아직 예약 CM 시간에 도달하지 않았습니다. Package Number : "+pkgNumber );
				}
			}
		} 
		
		HashMap<String,Object> result = new HashMap<String,Object>();
		result.put("status",status?"success":"fail");
		result.put("errorCode",errorCode);
		result.put("errorMsg",getMessage(errorCode));
        return new ModelAndView("jsonView", result );
   
    }
    
    /**
     * standby
     * CronTab 에서 호출(meaistan.sh) => meaidy0s.sh
     * /usr/java5/bin/java -classpath $CP_ARGS com.kbstar.eai.common.loader.DCStandbyLoader $APP_CONF/config/ >> $LOGFILE
     * 1. 일자전환 대상 통제 목록 DB 적재 후 동기화
     * tobe에서는 interfaceInfo 정보로 DB에 적재
     * ex) $APP_CONF/config/
     *     config(고정)
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=meaidy0s"})
    public ModelAndView meaidays(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	Properties prop = monitoringContext.getProperties();
		
    	String downloadPath   = prop.getProperty(MonitoringContext.CM_IOMAP_PATH, "/fscm/iomap/");

    	if (SystemUtil.isDevServer()){
    		HashMap<String,Object> result = new HashMap<String,Object>();
    		result.put("status","fail");
    		result.put("errorCode","999");
    		result.put("errorMsg","not support dev server");
            return new ModelAndView("jsonView", result );
    	}
		//String configPath = request.getParameter(CONFIGPATH); // Config File Path //1번 파라미터  <=== DB정보, TOBE에서는 사용하지 않음
		//String workDay    = request.getParameter(WORKDAY);    // 영업일자                   //2번 파라미터  <==영업일자는 일자전환에서만 사용
		String apCode     = ""; // 업무코드                   //3번 파라미터
		String pkgNumber  = ""; // 패키지번호                //4번 파라미터
		String runTime    = ""; // 실행시간                   //5번 파라미터
		String midNight   = ""; // 일자전환속성 Y/P/N  //6번 파라미터
		//String currentTime = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(ZonedDateTime.now());
		String nextTime = DatetimeUtil.getDate(1);
		
		boolean status    = true;
		String errorCode  = "000";
		List<HashMap> list = serviceMonitoring.selectTSEAIRM29("Y","N"); //일자전환 대상 이고 적용안된 패키지목록
		
		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			try{
				service.deleteAllTSEAIDC01();
			}catch(Exception e){
				smsSend("일자전환 서비스코드 삭제 오류 ["+dt.getText()+"] ");
			}
		}
		
		if (list == null || list.size()==0){
			logger.info("금일 일자전환 EAI 서비스 코드 데이터가 없습니다." );
		}else{
			for(HashMap map : list){
				apCode    = ((String)map.get("EAIBZWKDSTCD")).trim();     //업무구분코드
				pkgNumber = ((String)map.get("MODFIMGTPCKAGNO")).trim();  //패키지번호
				runTime   = ((String)map.get("MODFIMGTMODFIYMS")).trim(); //실행일자
				midNight  = ((String)map.get("DTECNVSNYN")).trim();       //일자전환여부
				if (runTime != null && "Y".equals(midNight) && nextTime.equals(runTime.substring(0,8))  ) {
					logger.info("일자전환 관련 EAI 서비스코드 등록이 시작 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다." );
					StopWatch sw = new StopWatch();
					sw.start();
					try{
						for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
							DataSourceContextHolder.setDataSourceType(dt);
								service.insertTSEAIDC01(downloadPath, apCode, pkgNumber,nextTime,dt);
						}
					}catch(Exception e){
						smsSend(pkgNumber,"일자전환 서비스코드 등록오류 ");
					}
					sw.stop();
					logger.info("일자전환 관련 EAI 서비스코드 등록이 완료 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString());
				}else{
					logger.info("일자전환 관련 EAI 서비스코드 패키지가 아닙니다. 패키지 번호는 "+pkgNumber+" 입니다.");

				}
			}
		}
		//TSEAIDC01 동기화
		CommonCommand command = new CommonCommand("com.eactive.eai.agent.businessday.ReloadBusinessDayCommand");
		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			try{
				if (!validate(agentUtilService.broadcast(command))){
					throw new Exception("TSEAIDC01 등록 오류" );
				}
			}catch(Exception e){
				smsSend("일자전환 서비스코드 메모리동기화 오류 ["+dt.getText()+"] ");
			}
		}	
    	
		HashMap<String,Object> result = new HashMap<String,Object>();
		result.put("status",status?"success":"fail");
		result.put("errorCode",errorCode);
		result.put("errorMsg",getMessage(errorCode));
        return new ModelAndView("jsonView", result );
    }
    /**
     * prepare
     * Control-M에서 호출(meaiprep.sh) => meaidy1p.sh
     * /usr/java5/bin/java -classpath $CP_ARGS com.kbstar.eai.common.loader.DCPrepareLoader $APP_CONF/config/ $1 >> $LOGFILE
     * 1. 일자전환 상태정보(P) 변경후 메모리 동기화
     * ex) $APP_CONF/config/ $1
     *    config(고정) 영업일자
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=meaidy1p"})
    public ModelAndView meaidayp(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	if (SystemUtil.isDevServer()){
    		HashMap<String,Object> result = new HashMap<String,Object>();
    		result.put("status","fail");
    		result.put("errorCode","999");
    		result.put("errorMsg","not support dev server");
            return new ModelAndView("jsonView", result );
    	}
    	
    	boolean status = true;
    	String errorCode = "000";
		//일자전환 상태정보 변경 및 동기화
		CommonCommand command = new CommonCommand("com.eactive.eai.agent.businessday.CDPrepareCommand");
		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			try{
				service.deleteAndInsertChangeStatus("P");
				if (!validate(agentUtilService.broadcast(command))){
					throw new Exception("Prepare CHANAGE_STATUS 변경 오류" );
				}
			}catch(Exception e){
				//status = false;
				//errorCode = "009";
				smsSend("일자전환 prepare 오류 ["+dt.getText()+"]");
				logger.error("Prepare 오류" + e.getMessage());
			}

		}
    	
		HashMap<String,Object> result = new HashMap<String,Object>();
		result.put("status",status?"success":"fail");
		result.put("errorCode",errorCode);
		result.put("errorMsg",getMessage(errorCode));
        return new ModelAndView("jsonView", result );
    }    
    
    /**
     * 일자전환
     * control-M에서 호출(meaicomm.sh) => meaidy2c.sh
     * /usr/java5/bin/java -classpath $CP_ARGS -DItsmPermIP=172.17.162.164 -DItsmPermPORT=3264 com.kbstar.eai.common.loader.DCCommitLoader $APP_CONF/config/ $1 >>$LOGFILE
     * 1.일자전환 케이스의 형상대상 DB 적재및 동기화
     * 2.일자전화 일자 변경후 동기화
     * 3.일자전환 상태정보(C) 변경 후 메모리 동기화
     * ex)$APP_CONF/config/ $1 
     *    config(고정) 영업일자
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=meaidy2c"})
    public ModelAndView meaidayc(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	Properties prop = monitoringContext.getProperties();
		
    	String downloadPath   = prop.getProperty(MonitoringContext.CM_IOMAP_PATH, "/fscm/iomap/");

    	if (SystemUtil.isDevServer()){
    		HashMap<String,Object> result = new HashMap<String,Object>();
    		result.put("status","fail");
    		result.put("errorCode","999");
    		result.put("errorMsg","not support dev server");
            return new ModelAndView("jsonView", result );
    	}
		//String configPath = request.getParameter(CONFIGPATH); // Config File Path //1번 파라미터  <=== DB정보, TOBE에서는 사용하지 않음
		String workDay    = request.getParameter(WORKDAY);    // 영업일자                   //2번 파라미터  <==영업일자는 일자전환에서만 사용
		String apCode     = ""; // 업무코드                   //3번 파라미터
		String pkgNumber  = ""; // 패키지번호                //4번 파라미터
		String runTime    = ""; // 실행시간                   //5번 파라미터
		String midNight   = ""; // 일자전환속성 Y/P/N  //6번 파라미터
		
		boolean status    = true;
		String errorCode  = "000";
		List<HashMap> list = serviceMonitoring.selectTSEAIRM29("Y","N");
		if (list == null || list.size()==0){
			logger.info("일자전환 CM DB에  대상 데이터가 없습니다." );
		}else{
			for(HashMap map : list){
				status = true;
				errorCode = "000";
				apCode    = ((String)map.get("EAIBZWKDSTCD")).trim();     //업무구분코드
				pkgNumber = ((String)map.get("MODFIMGTPCKAGNO")).trim();  //패키지번호
				runTime   = ((String)map.get("MODFIMGTMODFIYMS")).trim(); //실행일자
				midNight  = ((String)map.get("DTECNVSNYN")).trim();       //일자전환여부
				if(workDay != null){ //취약점소스 수정 2020.08.27
					if (runTime != null && "Y".equals(midNight) && workDay.equals(runTime.substring(0,8))  ) {
						StopWatch sw = new StopWatch();
						try{
							logger.info("일자전환 CM이 시작 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다." );
							sw.start();
							//1.CM 대상 파일 존재 여부(001)
							//2.IL02 저장 및 인터페이스 존재여부 check
							//3.CM 대상 파일 DB적재
							//4.CM 대상 파일 메모리 동기화
							errorCode = fileCheckAndDbInsertAndSync(downloadPath, apCode, pkgNumber);
							if (!"000".equals(errorCode)){
								status = false;
							}
							sw.stop();
							logger.info("일자전환 CM이 완료 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString());
							//il01 update //정상이든 오류든 EAI 적용여부는 Y
							serviceMonitoring.updateTSEAIRM29(pkgNumber, midNight, "Y", errorCode);
						}catch(Exception e){
							logger.error("일자전환 CM이 오류가 발생 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString());
							smsSend(pkgNumber,"일자전환 CM 오류");
						}finally{
							if (!status){
								smsSend(pkgNumber,getMessage(errorCode));
								//초기화
								status = true;
								errorCode = "000";
							}
						}
					}else{
						logger.info("일자전환 CM이 아닙니다. 패키지 번호는 "+pkgNumber+" 입니다.");

					}
				}
				
			}
		} 
		//일자전환 및 상태 정보 실행
		CommonCommand command = new CommonCommand("com.eactive.eai.agent.businessday.ChangeDateCommand",workDay);
		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			try{
				service.deleteAndInsertBusinessDayChange(workDay);
				if (!validate(agentUtilService.broadcast(command))){
					throw new Exception("일자전환 일자변경 오류 " + workDay );
				}
			}catch(Exception e){
				smsSend("일자전환 일자 변경오류 ["+dt.getText()+"]");
				//status = false;
				logger.error("일자전환 오류" + e.getMessage(),e);
			}		
		}
		
		HashMap<String,Object> result = new HashMap<String,Object>();
		result.put("status",status?"success":"fail");
		result.put("errorCode",errorCode);
		result.put("errorMsg",getMessage(errorCode));
        return new ModelAndView("jsonView", result );
   
    }    
    /**
     * finish
     * Control-M에서 호출(meaifini.sh) => meaidy3f.sh
     * /usr/java5/bin/java -classpath $CP_ARGS com.kbstar.eai.common.loader.DCFinishLoader $APP_CONF/config/ >> $LOGFILE
     * 1. 일자전환 대상 통제 목록 DB 삭제 후 동기화
     * 2. 일자전환 상태정보(F) 변경 후 메모리 동기화
     * ex) $APP_CONF/config/
     *     config(고정)
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=meaidy3f"})
    public ModelAndView meaidayf(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	return finish(request,response);
    }
    
    /**
     * ipl prepare
     * Control-M에서 호출(meaiipls.sh) => meaipl1p.sh
     * /usr/java5/bin/java -classpath $CP_ARGS com.kbstar.eai.common.loader.IPLStandbyLoader $APP_CONF/config/ >> $LOGFILE
     * 1. IPL 대상 통제 목록 DB 적재 후 동기화
     * 2. 일자전환 상태정보(P) 변경 후  메모리 동기화
     * ex) $APP_CONF/config/
     *    config(고정)
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=meaipl1p"})
    public ModelAndView meaiiplp(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	Properties prop = monitoringContext.getProperties();
		
    	String downloadPath   = prop.getProperty(MonitoringContext.CM_IOMAP_PATH, "/fscm/iomap/");

    	if (SystemUtil.isDevServer()){
    		HashMap<String,Object> result = new HashMap<String,Object>();
    		result.put("status","fail");
    		result.put("errorCode","999");
    		result.put("errorMsg","not support dev server");
            return new ModelAndView("jsonView", result );
    	}
		//String configPath = request.getParameter(CONFIGPATH); // Config File Path //1번 파라미터  <=== DB정보, TOBE에서는 사용하지 않음
		//String workDay    = request.getParameter(WORKDAY);    // 영업일자                   //2번 파라미터  <==영업일자는 일자전환에서만 사용
		String apCode     = ""; // 업무코드                   //3번 파라미터
		String pkgNumber  = ""; // 패키지번호                //4번 파라미터
		String runTime    = ""; // 실행시간                   //5번 파라미터
		String midNight   = ""; // 일자전환속성 Y/P/N  //6번 파라미터
		//String currentTime = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(ZonedDateTime.now());
		String nextTime = DatetimeUtil.getDate(0);
		
		boolean status    = true;
		String errorCode  = "000";
		List<HashMap> list = serviceMonitoring.selectTSEAIRM29("P","N"); //IPL 대상 이고 적용안된 패키지목록
		
		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			try{
				service.deleteAllTSEAIDC01();
			}catch(Exception e){
				smsSend("IPL prepare 오류 ["+dt.getText()+"]");
				logger.error("IPL Prepare 오류" + e.getMessage());
			}
		}
		
		if (list == null || list.size()==0){
			logger.info("금일 IPL EAI 서비스 코드 데이터가 없습니다." );
		}else{
			for(HashMap map : list){
				apCode    = ((String)map.get("EAIBZWKDSTCD")).trim();     //업무구분코드
				pkgNumber = ((String)map.get("MODFIMGTPCKAGNO")).trim();  //패키지번호
				runTime   = ((String)map.get("MODFIMGTMODFIYMS")).trim(); //실행일자
				midNight  = ((String)map.get("DTECNVSNYN")).trim();       //일자전환여부
				if (runTime != null && "P".equals(midNight) && nextTime.equals(runTime.substring(0,8))  ) {
					logger.info("IPL 관련 EAI 서비스코드 등록이 시작 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다." );
					StopWatch sw = new StopWatch();
					sw.start();
					try{
						for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
							DataSourceContextHolder.setDataSourceType(dt);
							service.insertTSEAIDC01(downloadPath, apCode, pkgNumber,nextTime,dt);
						}
					}catch(Exception e ){
						smsSend(pkgNumber,"IPL 서비스코드 등록 오류");
					}
					
					sw.stop();
					logger.info("IPL 관련 EAI 서비스코드 등록이 완료 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString());
				}else{
					logger.info("IPL 관련 패키기에 해당하는 CM이 없습니다. 패키지 번호는 "+pkgNumber+" 입니다.");

				}
			}
		}
		CommonCommand command = new CommonCommand("com.eactive.eai.agent.businessday.ReloadBusinessDayCommand");
		CommonCommand command2 = new CommonCommand("com.eactive.eai.agent.businessday.CDPrepareCommand");
		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			try{
				//TSEAIDC01 동기화
				if (!validate(agentUtilService.broadcast(command))){
					throw new Exception("TSEAIDC01 등록 오류" );
				}
				//일자전환 상태정보 변경 및 동기화
				service.deleteAndInsertChangeStatus("P");
				if (!validate(agentUtilService.broadcast(command2))){
					throw new Exception("Prepare CHANAGE_STATUS 변경 오류" );
				}
			}catch(Exception e){
				logger.error("IPL prepare 오류" + e.getMessage(),e);
				smsSend("IPL prepare 오류 ["+dt.getText()+"]");
			}
		}	

		
		HashMap<String,Object> result = new HashMap<String,Object>();
		result.put("status",status?"success":"fail");
		result.put("errorCode",errorCode);
		result.put("errorMsg",getMessage(errorCode));
        return new ModelAndView("jsonView", result );
    }    
    
    /**
     * IPL
     * Control-M에서 호출(meaiiplc.sh) => meaipl2c
     * /usr/java5/bin/java -classpath $CP_ARGS -DItsmPermIP=172.17.162.164 -DItsmPermPORT=3264 com.kbstar.eai.common.loader.AfterIPLLoader $APP_CONF/config/ $1  >>$LOGFILE
     * 1.IPL 케이스의 형상대상 DB 적재및 동기화
     * 2.일자전환 상태정보(C) 변경후 메모리 동기화
     * ex)$APP_CONF/config/ $1
     *    config(고정) 영업일자
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=meaipl2c"})
    public ModelAndView meaiiplc(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	Properties prop = monitoringContext.getProperties();
		
    	String downloadPath   = prop.getProperty(MonitoringContext.CM_IOMAP_PATH, "/fscm/iomap/");

    	if (SystemUtil.isDevServer()){
    		HashMap<String,Object> result = new HashMap<String,Object>();
    		result.put("status","fail");
    		result.put("errorCode","999");
    		result.put("errorMsg","not support dev server");
            return new ModelAndView("jsonView", result );
    	}
		//String configPath = request.getParameter(CONFIGPATH); // Config File Path //1번 파라미터  <=== DB정보, TOBE에서는 사용하지 않음
		String workDay    = request.getParameter(WORKDAY);    // 영업일자                   //2번 파라미터  <==영업일자는 일자전환에서만 사용
		String apCode     = ""; // 업무코드                   //3번 파라미터
		String pkgNumber  = ""; // 패키지번호                //4번 파라미터
		String runTime    = ""; // 실행시간                   //5번 파라미터
		String midNight   = ""; // 일자전환속성 Y/P/N  //6번 파라미터
		
		boolean status    = true;
		String errorCode  = "000";
		List<HashMap> list = serviceMonitoring.selectTSEAIRM29("P","N");
		if (list == null || list.size()==0){
			logger.info("IPL CM DB에  대상 데이터가 없습니다." );
		}else{
			for(HashMap map : list){
				status    = true;
				errorCode  = "000";
				apCode    = ((String)map.get("EAIBZWKDSTCD")).trim();     //업무구분코드
				pkgNumber = ((String)map.get("MODFIMGTPCKAGNO")).trim();  //패키지번호
				runTime   = ((String)map.get("MODFIMGTMODFIYMS")).trim(); //실행일자
				midNight  = ((String)map.get("DTECNVSNYN")).trim();       //일자전환여부
				if(workDay != null){ //취약점소스 수정 2020.08.27
					if ( "P".equals(midNight) && workDay.equals(runTime.substring(0,8))) {
						StopWatch sw = new StopWatch();
						try{
							logger.info("IPL CM이 시작 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다." );
							sw.start();
							//1.CM 대상 파일 존재 여부(001)
							//2.IL02 저장 및 인터페이스 존재여부 check
							//3.CM 대상 파일 DB적재
							//4.CM 대상 파일 메모리 동기화
							errorCode = fileCheckAndDbInsertAndSync(downloadPath, apCode, pkgNumber);
							if (!"000".equals(errorCode)){
								status = false;
							}
							sw.stop();
							logger.info("IPL CM이 완료 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString());
							//il01 update //정상이든 오류든 EAI 적용여부는 Y
							serviceMonitoring.updateTSEAIRM29(pkgNumber, midNight, "Y", errorCode);
						}catch(Exception e){
							logger.error("IPL CM이 오류가 발생 되었습니다. 패키지 번호는  " + pkgNumber + " 입니다. 상태 :"+status+" 수행시간 : " + sw.toString(),e);
							smsSend(pkgNumber,"IPL CM 오류");
						}finally{
							if (!status){
								smsSend(pkgNumber,getMessage(errorCode));
								//초기화
								status    = true;
								errorCode  = "000";
							}
						}
					}else{
						logger.info("IPL 날짜와 틀린 데이터가 남아있습니다. 확인해보십시요. Package Number :" + pkgNumber);

					}
				}
				
			}
		} 
		//일자전환 상태정보 변경 및 동기화
		CommonCommand command = new CommonCommand("com.eactive.eai.agent.businessday.ChangeDateCommand",workDay);
		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			try{
				service.deleteAndInsertBusinessDayChange(workDay);
				if (!validate(agentUtilService.broadcast(command))){
					throw new Exception("일자전환 오류 " + workDay );
				}
			}catch(Exception e){
				smsSend("IPL 일자 변경오류 ["+dt.getText()+"]");
				//status = false;
				logger.error("IPL 일자 변경오류 " + e.getMessage());
			}
		}
		
		HashMap<String,Object> result = new HashMap<String,Object>();
		result.put("status",status?"success":"fail");
		result.put("errorCode",errorCode);
		result.put("errorMsg",getMessage(errorCode));
        return new ModelAndView("jsonView", result );
    }  
    /**
     * finish
     * Control-M에서 호출(meaiiplf.sh) => meaidy3f.sh
     * /usr/java5/bin/java -classpath $CP_ARGS com.kbstar.eai.common.loader.DCFinishLoader $APP_CONF/config/ >> $LOGFILE
     * 1. 일자전환 대상 통제 목록 DB 삭제 후 동기화
     * 2. 일자전환 상태정보(F) 변경 후 메모리 동기화
     * ex) $APP_CONF/config/
     *     config(고정)
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm","type=meaipl3f"})
    public ModelAndView meaiiplf(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	return finish(request,response);
    }
    private ModelAndView finish(HttpServletRequest request, HttpServletResponse response){
    	if (SystemUtil.isDevServer()){
    		HashMap<String,Object> result = new HashMap<String,Object>();
    		result.put("status","fail");
    		result.put("errorCode","999");
    		result.put("errorMsg","not support dev server");
            return new ModelAndView("jsonView", result );
    	}
    	
    	boolean status = true;
    	String errorCode = "000";
    	
		CommonCommand command = new CommonCommand("com.eactive.eai.agent.businessday.ReloadBusinessDayCommand");
		CommonCommand command2 = new CommonCommand("com.eactive.eai.agent.businessday.CDFinishCommand");
		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			try{
				//TSEAIDC01 삭제
				service.deleteAllTSEAIDC01();
				//TSEAIDC01 메모리 동기화
				if (!validate(agentUtilService.broadcast(command))){
					throw new Exception("TSEAIDC01 삭제 오류" );
				}
				//일자전환 상태정보 변경 및 동기화
				service.deleteAndInsertChangeStatus("F");
				if (!validate(agentUtilService.broadcast(command2))){
					throw new Exception("Finish CHANAGE_STATUS 변경 오류" );
				}			
			}catch(Exception e){
				//status = false;
				//errorCode ="009";
				smsSend("일자 전환 종료 오류 ["+dt.getText()+"]");
				logger.error("Finish 오류" + e.getMessage());
			}
		}		
    	
		HashMap<String,Object> result = new HashMap<String,Object>();
		result.put("status",status?"success":"fail");
		result.put("errorCode",errorCode);
		result.put("errorMsg",getMessage(errorCode));
        return new ModelAndView("jsonView", result );
    }
//    /**
//     * makeCmFile
//     * 1. 일자전환 대상 통제 목록 추출
//     * tobe 에서는 화면에서 추출하기 때문에 필요없음 
//     * @param request
//     * @param response
//     * @return
//     * @throws Exception
//     */
//    @RequestMapping(value= "/ioMapLoader.do", params={"cmd=iocm,type=makeCmFile"})
//    public ModelAndView makeCmFile(HttpServletRequest request, HttpServletResponse response) throws Exception {
//		boolean status = true;
//    	final boolean resultStatus = status;
//        return new ModelAndView("jsonView", new HashMap<String,Object>(){{put("status",resultStatus?"success":"fail");}});
//    }





    /**
     * File 체크 , DB Insert 및 동기화 작업
     * 1.CM 대상 파일 존재 여부(001)
	 * 2.IL02 저장 및 인터페이스 존재여부 check
	 * 3.CM 대상 파일 DB적재
	 * 4.CM 대상 파일 메모리 동기화
	 * 
     * @param downloadPath
     * @param apCode
     * @param pkgNumber
     * @return
     * @throws Exception
     */
    private String fileCheckAndDbInsertAndSync(String downloadPath, String apCode, String pkgNumber) throws Exception{
		String errorCode ="000";
    	try{
			//1.CM 대상 파일 존재 여부(001)
			boolean result    = serviceMonitoring.checkFileList(downloadPath, apCode, pkgNumber);
			if (!result){
				throw new BizException("001");
			}
			//EAI 서비스코드 존재 여부(003) //db rollback 때문에 try catch 로 잡음
			//2.IL02 저장 및 인터페이스 존재여부 check
			try{
		    	for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
		    		DataSourceContextHolder.setDataSourceType(dt);
		    		service.insertTSEAIIL02AndCheck(downloadPath, apCode, pkgNumber, dt.getName());
		    	}
			}catch(Exception e){
				logger.error("insertTSEAIIL02AndCheck error ",e);
				throw new BizException("003");
			}
			//3.CM 대상 파일 DB적재
			HashMap<String,HashMap<String,Vector<String>>> data = new HashMap<String,HashMap<String,Vector<String>>>();
	    	for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
	    		DataSourceContextHolder.setDataSourceType(dt);
	    		service.insertDB(downloadPath, apCode, pkgNumber, dt, data);
	    	}
			//4.CM 대상 파일 메모리 동기화
			dataMemorySync(data);
		}catch(BizException be){
			//bizException 일경우는 하위의 값을 사용
			errorCode = be.getMessage();
			;
		}catch(Exception e){
			//CM 소스파일 정합성 체크(002)
			errorCode = "002";
			logger.error("fileCheckAndDbInsertAndSync error",e);
		}
		return errorCode;
    }
    private String getMessage(String errorCode){
		String errorMsg = "정상처리되었습니다.";
		
		//소스점검 수정 20201026
		if ("001".equals(errorCode)) {
    		errorMsg = "디렉토리에 CM파일 없음";
    	}else if ("002".equals(errorCode)) {
    		errorMsg = "CM 소스파일 정합성 체크";
    	}else if ("003".equals(errorCode)) {
    		errorMsg = "EAI 서비스코드 없음. 시스템인터페이스목록 작성하여 ITSM 기타서비스요청으로 운영적용신청바람";
	    }else if ("009".equals(errorCode)) {
	    	errorMsg = "기타오류";
	    }
		return errorMsg;
    }
    private void smsSend(String pkgNumber, String errorMsg){
    	//sms 전송
		//String errorMsg = getMessage(errorCode);
		String SMS_msg = "[EAI] IOMAP CM ERROR - 패키지번호 : " + pkgNumber + " , " + errorMsg;
		logger.error(SMS_msg);
		try{
			String sms_ip = monitoringContext.getStringProperty(MonitoringContext.ITSMPERM_IP,"");
    		String sms_port = monitoringContext.getStringProperty(MonitoringContext.ITSMPERM_PORT,"");

    		HashMap<String, String> map = new HashMap();
    		map.put("ItsmPermIP", sms_ip);
    		map.put("ItsmPermPORT", sms_port);
			ItsmSmsSender.sendGroupSMS(map,ItsmSmsSender.EAI_GRP_MODE,ItsmSmsSender.EAI_GRP_MODE,SMS_msg);
		}catch(Exception e){
			logger.error("IoMapLoaderController] ITSM_SMS Send error "+e.getMessage(),e);
		}
    }

    private void smsSend(String errorMsg){
    	//sms 전송
    	String SMS_msg = "[EAI] IOMAP CM ERROR : " + errorMsg;
    	logger.error(SMS_msg);
    	try{
    		
    		String sms_ip = monitoringContext.getStringProperty(MonitoringContext.ITSMPERM_IP,"");
    		String sms_port = monitoringContext.getStringProperty(MonitoringContext.ITSMPERM_PORT,"");

    		HashMap<String, String> map = new HashMap<>();
    		map.put("ItsmPermIP", sms_ip);
    		map.put("ItsmPermPORT", sms_port);
    		
    		ItsmSmsSender.sendGroupSMS(map,ItsmSmsSender.EAI_GRP_MODE,ItsmSmsSender.EAI_GRP_MODE,SMS_msg);
    	}catch(Exception e){
    		logger.error("IoMapLoaderController] ITSM_SMS Send error "+e.getMessage(),e);
    	}
    }
    private boolean validate(HashMap<String,Object> map ){
    	for(String key : map.keySet()){
    		Object o = map.get(key);
    		if (o instanceof String){
    			if("success".equals((String)o)){
    				;
    			}else{
    				return false;
    			}
    		}else{
    			return false;
    		}
    	}
    	return true;
    }

    private void dataMemorySync(HashMap<String,HashMap<String,Vector<String>>> syncData ) throws Exception{

		//레이아웃/변환/EAI서비스코드 동기화
		HashMap<String,Vector<String>> serverType = null;
		Vector<String> v = null;
		CommonCommand command = null;

		for(DataSourceType dt : DataSourceTypeManager.getOnlineDataSourceTypes()){
			DataSourceContextHolder.setDataSourceType(dt);
			if (syncData.containsKey(dt.getName())){
				serverType = syncData.get(dt.getName());
				if (serverType.containsKey(LAYOUT)){
					v = serverType.get(LAYOUT);
					Vector<String> v2 = (Vector<String>) v.stream().distinct().collect(Collectors.toCollection(Vector::new));
					command = new CommonCommand("com.eactive.eai.agent.transformer.ReloadLayoutListCommand",v2);
					if (!validate(agentUtilService.broadcast(command))){
						throw new Exception("레이아웃 동기화 오류 " + v2 );
					}
				}
			}
			if (syncData.containsKey(dt.getName())){
				serverType = syncData.get(dt.getName());
				if (serverType.containsKey(TRANSFORM)){
					v = serverType.get(TRANSFORM);
					Vector<String> v2 = (Vector<String>) v.stream().distinct().collect(Collectors.toCollection(Vector::new));
					command = new CommonCommand("com.eactive.eai.agent.transformer.ReloadTransformListCommand",v2);
					if (!validate(agentUtilService.broadcast(command))){
						throw new Exception("변환 동기화 오류 " + v2 );
					}
				}
			}
			if (syncData.containsKey(dt.getName())){
				serverType = syncData.get(dt.getName());
				if (serverType.containsKey(INTERFACE)){
					v = serverType.get(INTERFACE);
					Vector<String> v2 = (Vector<String>) v.stream().distinct().collect(Collectors.toCollection(Vector::new));
					command = new CommonCommand("com.eactive.eai.agent.eaimessage.ReloadEAIMessageListCommand",v2);
					if (!validate(agentUtilService.broadcast(command))){
						throw new Exception("인터페이스 동기화 오류 " + v2 );
					}
				}
			}
		}
    }
}
