
package com.eactive.eai.rms.bat.loader.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

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

import com.eactive.eai.agent.command.Command;
import com.eactive.eai.agent.command.CommonCommand;
import com.eactive.eai.rms.bat.loader.dao.BatLoaderDaoImpl;
import com.eactive.eai.rms.bat.manage.rule.inter.BatInterfaceDao;
import com.eactive.eai.rms.common.base.BaseService;
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.onl.common.service.AgentUtilService;
import com.eactive.eai.rms.onl.common.util.DateUtil;
import com.eactive.eai.rms.onl.common.util.FileUtils;
import com.eactive.eai.rms.onl.common.util.FileWriteUtil;
import com.eactive.eai.rms.onl.loader.service.TransactionLoaderService;
import com.eactive.eai.rms.onl.loader.vo.RuleDeployJobItemVo;
import com.eactive.eai.rms.onl.loader.vo.RuleDeployJobVo;

@Service("batLoaderService")
public class TransactionLoaderServiceImpl extends BaseService {
	
	public static String BAT_INTERFACE 	= "interface";

    /** The monitoring context. */
    @Autowired
    @Qualifier("monitoringContext")
    private transient MonitoringContext monitoringContext;

    @Autowired
    @Qualifier("batLoaderDao")
    private BatLoaderDaoImpl dao;
    
    @Autowired
	@Qualifier("batInterfaceDao")
	private BatInterfaceDao batIntfDao;
    
    @Autowired
	private TransactionLoaderService loaderService;
    
    @Autowired
	@Qualifier("batAgentUtilService")
	public AgentUtilService batAgentUtilService;
    
    public TransactionLoaderServiceImpl() { 
        super();
    }


    /**
     * interface loading
     */
    public void insertInterfaceLoading(DataSourceType dt, String path,String fileName)
    throws Exception {
//    	TSEAIEA04 인터페이스
//    	TSEAIEA02 아답터
//    	TSEAIEA05 file아답터
//    	TSEAIEA03 DB아답터
//    	TSEAIES07 스케쥴
//    	TSEAIES09 스케쥴sub

    	//String[] tables = {"TSEAIEA04","TSEAIEA02","TSEAIEA03","TSEAIEA05","TSEAIES07","TSEAIES09"}; 
    	String[] tables = {"TSEAIEA04","TSEAIEA03","TSEAIEA05","TSEAIES07","TSEAIES09"}; 
		HashMap map = parse(path + fileName);
		if(map !=null) {
			//adapter 존재여부 체크
			
			insertTableLoading(dt,tables, path, fileName);
		}
    }     
    
      
    /**
     * interface downloading
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public void interfaceDownLoading(DataSourceType dt, String path,String eaiSvcName)   throws Exception {
        LinkedHashMap<String,List> tables= new LinkedHashMap<String,List>();

        List<LinkedHashMap> listEA04 = dao.selectTableData(dt,"TSEAIEA04", "INTFID", eaiSvcName);  
        if( listEA04 == null || listEA04.size() == 0) {
        	throw new Exception ("interface data is empty  interfaceName =["+eaiSvcName+"]") ;
        }
        LinkedHashMap intfMap = listEA04.get(0);
        String batType = (String)intfMap.get("BATCHTYPE");
        String sndAdptr= (String)intfMap.get("SNDADPTRCD");

//        HashMap<String, Object> params = new HashMap<String, Object>();
//        params.put("intfId", eaiSvcName);
//        params.put("sndRcvKind", "2");
            	
    	tables.put("TSEAIEA04",listEA04);  
        
        if(batType.equals("DD") == true) {       
        	//List<LinkedHashMap> listEA02 = new ArrayList<LinkedHashMap>() ;
        	List<LinkedHashMap> listEA03 = dao.selectDbAdapterTableData(dt, "TSEAIEA03", "INTFID", eaiSvcName);
        	tables.put("TSEAIEA03",listEA03);
        } else if(batType.equals("FF") == true) {
        	List<LinkedHashMap> listEA05 = dao.selectTableData(dt, "TSEAIEA05", "INTFID", eaiSvcName);
        	tables.put("TSEAIEA05",listEA05);
        } else {
        	throw new Exception("지원하지않는 배치타입 입니다.");
        }
       
        List<LinkedHashMap> listES09 = dao.selectTableData(dt, "TSEAIES09", "INTFID", eaiSvcName);
        
        if( listES09 == null || listES09.size() == 0) {
        	throw new Exception ("schedule-interface data is empty  interfaceName =["+eaiSvcName+"]") ;
        }
        LinkedHashMap scheduleMap = listES09.get(0);
        String schedule = (String)scheduleMap.get("BJOBMSGSCHEID");
        
        List<LinkedHashMap> listES07 = dao.selectTableData(dt, "TSEAIES07", "BJOBMSGSCHEID", schedule);
    	
        tables.put("TSEAIES07",listES07);
        tables.put("TSEAIES09",listES09);
       
        FileWriteUtil.FileWrite(path , eaiSvcName+".txt", tables);
    }         
     
    /**
     * interface download all
     */
    public void interfaceDownLoadingAll(DataSourceType dt, String serviceType) throws Exception {
        String iomapPath = monitoringContext.getStringProperty(MonitoringContext.IOMAP_DOWNLOAD_PATH);
        String path = "";
        List elist = new ArrayList();
    	List<LinkedHashMap> list =  dao.selectTableDataLike(dt,"TSEAIHE01", "EAISvcName", "%");
    	for (int i=0;i<list.size();i++){
    		LinkedHashMap lm = list.get(i);
    		String eaiSvcName = (String)lm.get("EAISVCNAME");
    		String bzwkDstcd = ((String)lm.get("EAIBZWKDSTCD")).trim();
    		path = iomapPath + serviceType + File.separator + bzwkDstcd + File.separator + FileWriteUtil.INTERFACE + File.separator ;
    		try{
    			interfaceDownLoading( dt,  path, eaiSvcName);
    		}catch(Exception e){
    			
    			elist.add(eaiSvcName);
    			//logger.error(error);
    		}
    	}
    	if(elist.size() > 0){
    		StringBuffer sb = new StringBuffer();
    		sb.append("interface data is empty  eaiSvcName =[");
    		for(int i = 0; i< elist.size(); i++){
    			sb.append(elist.get(i)+ ", ");
    		}
    		sb.append("]");
    		throw new Exception(sb.toString());
    	}
    } 
    
    /**
     * table loading
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public void insertTableLoading(DataSourceType dt,String[] tables , String path,String fileName) throws Exception {
    	if(fileName != null){ //취약점소스 수정 2020.08.27
        	HashMap map = parse(path + fileName);
    		if(map !=null) {
    			ArrayList list = null;
    			HashMap hm = new HashMap();
    			hm.put("schemaId", dt.getSchema());    	
    			//1. 인터페이스ID 추출
    			String interfaceId = "";
    			for (String table : tables){
    				list = (ArrayList)map.get(table);
    				if(list != null ? list.size() > 0 : false){ 
    					hm.put("tableName", table);
    					LinkedHashMap<String, Object> lhm= (LinkedHashMap<String, Object>)list.get(0);
    					if(table.equals("TSEAIEA04")) {
    						interfaceId = (String)lhm.get("INTFID");
    					}
    				}
    			}
    			if (StringUtils.isBlank(interfaceId)){
    				throw new Exception("interfaceId is blank");
    			}
    			//2. 어댑터 체크
    			String adapter = "";
    			for (String table : tables){
    				list = (ArrayList)map.get(table);
    				if(list != null ? list.size() > 0 : false){ 
    					hm.put("tableName", table);
    					LinkedHashMap<String, Object> lhm= (LinkedHashMap<String, Object>)list.get(0);
    					if(table.equals("TSEAIEA03") || table.equals("TSEAIEA05")) {
    						for(int i = 0; i< list.size(); i++) {
								lhm= (LinkedHashMap<String, Object>)list.get(i);
								adapter = (String)lhm.get("ADPTRCD");
								//어댑터 체크
								hm.put("adptrCd", adapter);
								try{
									HashMap result = batIntfDao.adapterDetail(hm);
									if (result == null || result.size()==0){
										throw new Exception("adapter("+adapter+") not found ");
									}
								}catch(Exception e){
									throw new Exception("adapter("+adapter+") not found ");
								}
    						}
    					}
    				}
    			}
    			
    			//2. 삭제 로직 추가
    			batIntfDao.deleteWholeInterface(interfaceId);
    			
    			for (String table : tables){
    				list = (ArrayList)map.get(table);
    				if(list != null ? list.size() > 0 : false){ 
    					hm.put("tableName", table);
    					
//    					if (table.equals("TSEAIEA04"))
//							((LinkedHashMap<String, Object>)list.get(0)).put("DELYN", "1");
    					
//    					LinkedHashMap<String, Object> lhm= (LinkedHashMap<String, Object>)list.get(0);
//    					if(table.equals("TSEAIEA04")) {
//    						String intfName = (String)lhm.get("INTFID");
//    						hm.put("key1", "INTFID");
//    						hm.put("value1", intfName);
////    						inboundErrorInfoDao.delete(dt, table, hm);
//    						batIntfDao.deleteWholeInterface(intfName);
////    					} else if(table.equals("TSEAIEA02")) {
////    						ArrayList listCopy = new ArrayList(list);
////    						for(int i = 0; i< listCopy.size(); i++) {
////    							lhm= (LinkedHashMap<String, Object>)listCopy.get(i);
////	    						String adptrcd = (String)lhm.get("ADPTRCD");
////	    						String workGrpCd = (String)lhm.get("WORKGRPCD");
////	    						hm.put("adptrCd", adptrcd);	    						
////	    						hm.put("workGrpCd", workGrpCd);
////	    						if( 1 <= inboundErrorInfoDao.selectTSEAI02Count(dt, hm))
////	    							list.remove(lhm);
////    						}
//    					} else if(table.equals("TSEAIEA03")) {
//    						for(int i = 0; i< list.size(); i++) {
//    							lhm= (LinkedHashMap<String, Object>)list.get(i);
//	    						String adptrcd = (String)lhm.get("ADPTRCD");
//	    						String workGrpCd = (String)lhm.get("WORKGRPCD");
//	    						String intfId = (String)lhm.get("INTFID");
//	    						if(adptrcd.isEmpty() == false) {
//	    							hm.put("key1", "ADPTRCD");
//		    						hm.put("value1", adptrcd);
//		    						hm.put("key2", "WORKGRPCD");
//		    						hm.put("value2", workGrpCd);
//		    						hm.put("key3", "INTFID");
//		    						hm.put("value3", intfId);
//		    						inboundErrorInfoDao.delete3Keys(dt, table, hm);
//	    						}
//    						}
//    					} else if(table.equals("TSEAIEA05")) {
//    						for(int i = 0; i< list.size(); i++) {
//    							lhm= (LinkedHashMap<String, Object>)list.get(i);
//	    						String adptrcd = (String)lhm.get("ADPTRCD");
//	    						String workGrpCd = (String)lhm.get("WORKGRPCD");
//	    						String intfId = (String)lhm.get("INTFID");
//	    						if(adptrcd.isEmpty() == false) {
//	    							hm.put("key1", "ADPTRCD");
//		    						hm.put("value1", adptrcd);
//		    						hm.put("key2", "WORKGRPCD");
//		    						hm.put("value2", workGrpCd);
//		    						hm.put("key3", "INTFID");
//		    						hm.put("value3", intfId);
//		    						inboundErrorInfoDao.delete3Keys(dt, table, hm);
//	    						}
//	    						String sysCode;
//    			        		sysCode = adptrcd.substring(0, 3);
//    			        		HashMap sysInfo =  inboundErrorInfoDao.selectSystemInfo(dt,sysCode );
//    			        		
//    			        		if(sysInfo == null) {
//    			        			throw new Exception("selectSystemInfo return is Null. sysCode : " + sysCode + " Please Check " + dt.getSchema() + ".TSEAIEJ02 TABLE");
//    			        		}
//    			        		lhm.put("FTPNAME", (String)sysInfo.get("CNTNDNS"));
//    			        		lhm.put("FTPNAMEDESC", (String)sysInfo.get("CNTNDNS"));
//    			        		lhm.put("FTPHOSTNAME", (String)sysInfo.get("CNTNDNS"));
//    			        		lhm.put("RMTSEVRFTPPORTNONAME", (String)sysInfo.get("APPORT"));
//    			        		lhm.put("RMTSEVRFTPUID", (String)sysInfo.get("CNTNID"));	
//    						}
//    					}  else if(table.equals("TSEAIES07")) {
//    						String schId = (String)lhm.get("BJOBMSGSCHEID");
//    						if(schId.isEmpty() == false) {
//    							hm.put("key1", "BJOBMSGSCHEID");
//	    						hm.put("value1", schId);
//	    						inboundErrorInfoDao.delete(dt, table, hm);
//    						}
//    					}  else if(table.equals("TSEAIES09")) {
//    						String schId = (String)lhm.get("BJOBMSGSCHEID");
//    						if(schId.isEmpty() == false) {
//    							hm.put("key1", "BJOBMSGSCHEID");
//	    						hm.put("value1", schId);
//	    						inboundErrorInfoDao.delete(dt, table, hm);
//    						}
//    					}
    					if(list.size() >0)
    						dao.insertTable( dt , table , list);
    				}
    			}
    		}
    	}
	}      
   
    /**
     * table downloading
     */
    public void tableDownLoading(DataSourceType dt, String path,String tableName) throws Exception {
        
        List<LinkedHashMap> table = dao.selectTable(dt, tableName, "1", "1");  

        if (table == null || table.size() == 0){
        	throw new Exception ("table data is empty  tableName =["+tableName+"]") ;
        }

        LinkedHashMap<String,List> tables= new LinkedHashMap<String,List>();
        tables.put(tableName,table);
        FileWriteUtil.FileWrite(path , tableName+".txt", tables);
		
    }     

	@SuppressWarnings("rawtypes")
	public HashMap parse(String filePath) throws Exception {
		HashMap map = new HashMap();
		
		FileReader fr = null;
		BufferedReader br = null;
		try{
			fr = new FileReader(filePath);
			if(fr == null) {
				return map;
			}
			br = new BufferedReader(fr);
			map = parseToString(br);
		}catch(Exception e){
			
		}finally{
			if (br != null)try{br.close();}catch(Exception e){}
			if (fr != null)try{fr.close();}catch(Exception e){}
		}
		return map;
	}
	/*
	 * parseToString() 부분의 기능이 재활용 가능성이 있어서
	 * 기존 parse()를 나눠서 parseToString()을 추가함.
	 * */
	public HashMap parseToString(BufferedReader br) throws Exception {
		String delimeter = ";";
		HashMap map = new HashMap();
		ArrayList list = null;
		
        String lbuff = null;
        String[] header = null;
        
        try {        	
			while ((lbuff = br.readLine()) != null) {
			
				if(lbuff.indexOf(delimeter) < 0) {
		        	list = new ArrayList();
		        	map.put(lbuff.toUpperCase(), list);
				
				if(lbuff.startsWith("TSEAIEA03") == true ) {
						if((lbuff = br.readLine()) == null) {	        		
			        		throw new Exception();
			        	}	
			        	header = lbuff.split(delimeter);
			        	
					    for(int i=0; i<3; i++) {							
							lbuff = br.readLine();
							String temp = new String(lbuff);
							lbuff = br.readLine();
							if(lbuff.startsWith("<DBSQL>") || lbuff.startsWith("<dbsql>") == true) {
								lbuff = lbuff.replace("<DBSQL>", "").replace("<dbsql>"	, "");								
								while(lbuff.endsWith("</DBSQL>") == false &&
										lbuff.endsWith("</dbsql>") == false) 
								{
									lbuff += "\r\n";
									lbuff+=br.readLine();
								}
								lbuff = lbuff.replace("</DBSQL>", "\r\n").replace("</dbsql>", "\r\n");
							}
							temp += lbuff;
							temp += br.readLine();
							LinkedHashMap codes = split(header,temp, delimeter, header.length);
							list.add(codes);							
					    }		
					    continue;
					} else {
						if((lbuff = br.readLine()) == null) {	        		
			        		throw new Exception();
			        	}	
			        	header = lbuff.split(delimeter);
			        	continue;
					}
				} 
				if(header == null) continue;
				LinkedHashMap codes = split(header,lbuff, delimeter, header.length);
				list.add(codes);
				}
        }catch(Exception ex) {
			logger.error("parse error : ", ex);
		}
        
        return map;
	}
	private LinkedHashMap split(String[] header, String data, String deli, int size) {
		LinkedHashMap array = new LinkedHashMap();
		String data2 = data + " " +deli;//마지막 에 ";;" 될경우 length 차이가 나서 보정해주는 로직 
		String[] s = data2.split(deli);
		for(int i=0; i<s.length-1;i++){
			array.put(header[i], s[i]);
		}
		return array;
	}

	public HashMap<String, ArrayList<HashMap<String, String>>> getInterfaceListByInterfaceIds(DataSourceType dt,
			String[] interfaceIds) throws Exception {
		HashMap<String, ArrayList<HashMap<String, String>>> list = new HashMap<String, ArrayList<HashMap<String, String>>>();
		ArrayList<HashMap<String, String>> lList = dao.getInterfaceListByInterfaceIds(dt, interfaceIds);
		if (!lList.isEmpty()) {
			list.put(BAT_INTERFACE, lList);
		}
		return list;
	}

	public void deployDataToTargetSystem(String url, String downloadPath,
			HashMap<String, ArrayList<HashMap<String, String>>> listMap, String serviceType) throws Exception {
		if (listMap.get(BAT_INTERFACE) != null && listMap.get(BAT_INTERFACE).size() > 0) {
			for (HashMap<String, String> data : listMap.get(BAT_INTERFACE)) {
				String filePath = downloadPath + data.get("bizCode") + File.separator + BAT_INTERFACE + File.separator
						+ data.get("programNm");
				loaderService.uploadDeployFile(url, filePath, BAT_INTERFACE, serviceType, data.get("bizCode"));
			}
		}
	}

	public String parseSimple(String serviceType, String iomapPath,
			HashMap<String, ArrayList<HashMap<String, String>>> list) throws Exception {
		String delimeter = "|";
		StringBuffer buffer = new StringBuffer();

		if (list.get(BAT_INTERFACE) != null && list.get(BAT_INTERFACE).size() > 0) {
			for (HashMap<String, String> data : list.get(BAT_INTERFACE)) {
				buffer.append(data.get("bizCode")).append(delimeter);
				buffer.append(data.get("UpdateBy")).append(delimeter);
				buffer.append(data.get("programNm")).append(delimeter);
				buffer.append(iomapPath).append(serviceType).append("/").append(data.get("bizCode")).append("/")
						.append(FileWriteUtil.TRANSFORM).append(delimeter);
				buffer.append(BAT_INTERFACE).append(delimeter);
				buffer.append("\n");
			}
		}

		return buffer.toString();
	}

	/**
	 * 룰정보 등록 및 메모리 적재 작업 수행
	 * Target 시스템에서 사용
	 */
	public boolean ruleDataSaveAndLoading(RuleDeployJobVo jobVo) throws Exception {
		if (jobVo == null || jobVo.getItemList() == null || jobVo.getItemList().size() == 0) {
			throw new Exception("No have rule datas");
		}

		if (!DataSourceTypeManager.isDynamicByName(jobVo.getServiceType())) {
			throw new Exception("Undefined service type. Received service type=" + jobVo.getServiceType());
		}

		String uploadPath = monitoringContext.getStringProperty(MonitoringContext.IOMAP_UPLOAD_PATH);
		uploadPath = StringUtils.removeEnd(uploadPath, File.separator) + File.separator + jobVo.getServiceType()
				+ File.separator;
		String savePath = monitoringContext.getStringProperty(MonitoringContext.IOMAP_AFTER_UPLOAD_PATH);

		DataSourceType dt = DataSourceTypeManager.getDataSourceType(jobVo.getServiceType());
		if (dt != null) {
			DataSourceContextHolder.setDataSourceType(dt);
		}

		for (RuleDeployJobItemVo itemVo : jobVo.getItemList()) {
			logger.debug("itemVo=" + itemVo.toString());
			HashMap result = null;
			String path = uploadPath + itemVo.getBizCode() + File.separator + itemVo.getRuleType() + File.separator;
			if (BAT_INTERFACE.equals(itemVo.getRuleType())) {
				insertInterfaceLoading(dt, path, itemVo.getFileName());
				result = syncResult(new CommonCommand("com.eactive.eai.agent.scheduler.ReloadBatchInterfaceJobCommand"),
						itemVo.getFileName());
			}

			if (result == null || ("error").equals((String) result.get("status"))) {
				throw new Exception(result.toString());
			} else {
				String today = DateUtil.getDateTime("yyyy-MM-dd");
				String newPath = savePath + today + File.separator + jobVo.getServiceType() + File.separator
						+ itemVo.getBizCode() + File.separator + itemVo.getRuleType() + File.separator;
				try {
					Boolean isMoved = FileUtils.moveFile(path, newPath, itemVo.getFileName(), itemVo.getFileName());
					if (isMoved) {
						logger.info(itemVo.getFileName() + " is moved to " + newPath);
					} else {
						logger.info(itemVo.getFileName() + " is moved NOT to " + newPath);
					}
				} catch (Exception e) {
					logger.info("Failed to move File");
				}
			}
		}

		return true;
	}
	
	public HashMap syncResult(Command command, String fileName) throws Exception {
		// layout 동기화 service 에는 transaction 때문에 문제의 소지가 있음
		HashMap receive = new HashMap();
		String[] name = fileName.split("\\.");
		if (name.length > 0 && name[0] != null) {
			command.setArgs(name[0]);
			receive = batAgentUtilService.broadcast(command);
		}

		String status = "success";
		for (Object o : receive.keySet()) {
			String key = (String) o;
			if (receive.get(key) == null || !"success".equals(receive.get(key))) {
				status = "error";
				break;
			}
		}
		HashMap result = new HashMap();
		result.put("status", status);
		result.put("message", receive.toString());

		if (logger.isInfoEnabled()) {
			logger.info(this.getClass().toString() + "] command = " + command.getClass().toString() + " fileName="
					+ fileName + " status = " + status + " message = " + receive.toString());
		}

		return result;
	}
}