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

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.eactive.eai.rms.common.acl.user.BizDao;
import com.eactive.eai.rms.common.base.OnlBaseService;
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.util.CommonUtil;
import com.eactive.eai.rms.common.util.StringUtils;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.eactive.eai.rms.onl.common.util.FileWriteUtil;
import com.eactive.eai.rms.onl.loader.service.TransactionLoaderService;
//import com.eactive.eai.rms.onl.manage.rule.aurora.AuroraUtil;
import com.eactive.eai.rms.onl.manage.rule.layout.LayoutDao;
import com.eactive.eai.rms.onl.manage.rule.upload.IoMapLoaderKey;
import com.eactive.eai.rms.onl.manage.rule.upload.IoMapLoaderService;
import com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg.EaiMsgDao;

import edu.emory.mathcs.backport.java.util.Arrays;

@Service
public class TransformManService extends OnlBaseService {

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

	@Autowired
	@Qualifier("transformDao")
	private TransformDao transformDao;

	@Autowired
	@Qualifier("layoutDao")
	private LayoutDao layoutDao;

	@Autowired
	private EaiMsgDao eaiMessageDAO;

	@Autowired
	@Qualifier("bizDao")
	private BizDao bizDao;

	@Autowired
	@Qualifier("loaderService")
	private TransactionLoaderService loaderService;

	@Autowired
	@Qualifier("ioMapLoaderService")
	private IoMapLoaderService ioMapLoaderService;

	/**
	 * 변환규칙 list 조회
	 */
	public HashMap selectList(int startNum, int endNum, String searchBizCode, String searchCnvsnName,
			String searchCnvsnDesc) throws Exception {
		HashMap paramMap = new HashMap();
		paramMap.put("searchBizCode", searchBizCode);
		paramMap.put("searchCnvsnName", searchCnvsnName);
		paramMap.put("searchCnvsnDesc", searchCnvsnDesc);

		// 전체 목록수 얻기
		int totalCount = transformDao.selectListCount(paramMap);
		paramMap.put("startNum" , startNum);// 시작 record
		paramMap.put("endNum"   , endNum);// 끝 record

		List list = transformDao.selectList(paramMap);
		HashMap map = new HashMap();
		map.put("totalCount", totalCount);

		map.put("list", list);

		return map;
	}

	/**
	 * 변환규칙 레이아웃 항목들 조회
	 */
	public List selectLayoutItems(String loutName) {
		HashMap paramMap = new HashMap();
		paramMap.put("loutName", loutName);
		return transformDao.selectLayoutItems(paramMap);
	}

	public List selectTransformItems(String cnvsnName, String loutName) {
		String tgtLoutName = "";
		HashMap paramMap = new HashMap();
		paramMap.put("cnvsnName", cnvsnName);
		paramMap.put("layoutType", "TGT_LAYOUT");
		List list = transformDao.selectTransformSourceResult(paramMap);
		if (list != null || list.size() == 1) {
			HashMap h = (HashMap) list.get(0);
			tgtLoutName = (String) h.get("LOUTNAME");
		}
		if ("".equals(tgtLoutName)) {
			paramMap.put("loutName", loutName);
			return transformDao.selectLayoutItems(paramMap);
		} else {
			paramMap.put("loutName", tgtLoutName);
			List<HashMap> loutList = transformDao.selectLayoutItems(paramMap);
			List<HashMap> transformList = transformDao.selectTransformItems(paramMap);

			for (HashMap trVo : transformList) {
				for (HashMap layoutVo : loutList) {
					String resultFullPath = (String) trVo.get("CNVSNRSULTITEMPATHNAME");
					String loutItemPath = (String) layoutVo.get("LOUTITEMPATH");

					if (resultFullPath.endsWith(loutItemPath)) {
						layoutVo.put("CNVSNNAME", trVo.get("CNVSNNAME"));
						layoutVo.put("CNVSNRSULTITEMPATHNAME", trVo.get("CNVSNRSULTITEMPATHNAME"));
						layoutVo.put("CNVSNCMDNAME", trVo.get("CNVSNCMDNAME"));
						layoutVo.put("CNVSNITEMBASCVAL", trVo.get("CNVSNITEMBASCVAL"));
						layoutVo.put("CNVSNITEMSERNO", trVo.get("CNVSNITEMSERNO"));
						break;
						// 배열항목 ( [*], [1] 등 ) 값 비교를 위해서 다음을 추가한다
					} else if (CommonUtil.removeArrayTag(resultFullPath).endsWith(loutItemPath)) {
						layoutVo.put("CNVSNNAME", trVo.get("CNVSNNAME"));
						layoutVo.put("CNVSNRSULTITEMPATHNAME", trVo.get("CNVSNRSULTITEMPATHNAME"));
						layoutVo.put("CNVSNCMDNAME", trVo.get("CNVSNCMDNAME"));
						layoutVo.put("CNVSNITEMBASCVAL", trVo.get("CNVSNITEMBASCVAL"));
						layoutVo.put("CNVSNITEMSERNO", trVo.get("CNVSNITEMSERNO"));
						break;
					}

				}
			}
			return loutList;
		}
	}

	public List selectTransformSourceResult(String cnvsnName) {
		HashMap paramMap = new HashMap();
		paramMap.put("cnvsnName", cnvsnName);
		return transformDao.selectTransformSourceResult(paramMap);
	}

	public List selectLayoutCombo(String eaiBzwkDstcd) {
		HashMap paramMap = new HashMap();
		paramMap.put("eaiBzwkDstcd", eaiBzwkDstcd);
		return transformDao.selectLayoutCombo(paramMap);
	}

	public List selectFunctionCombo() {
		HashMap paramMap = new HashMap();
		return transformDao.selectFunctionCombo(paramMap);
	}

	public List selectTransformForEaiSvcNameCombo(String eaiSvcName) {
		HashMap paramMap = new HashMap();
		paramMap.put("eaiSvcName", eaiSvcName);
		return transformDao.selectTransfomForEaiSvcNameCombo(paramMap);
	}

	public HashMap selectPopList(int startNum, int endNum, String loutName) throws Exception {

		HashMap<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("loutName", loutName);
		// 전체 목록수 얻기
		int totalCount = layoutDao.selectListCount(paramMap);

		paramMap.put("startNum" , startNum);// 시작 record
		paramMap.put("endNum"   , endNum);// 끝 record

		List<Map<String, Object>> list = transformDao.selectLayoutCombo(paramMap);
		HashMap<String, Object> map = new HashMap<String, Object>();

		map.put("totalCount", totalCount);
		map.put("list", list);

		return map;
	}

	public HashMap selectLayoutList(int startNum, int endNum, HashMap paramMap) throws Exception {

		// 전체 목록수 얻기
		int totalCount = transformDao.selectLayoutListCount(paramMap);

		paramMap.put("startNum" , startNum);// 시작 record
		paramMap.put("endNum"   , endNum);// 끝 record

		List list = transformDao.selectLayoutList(paramMap);

		HashMap map = new HashMap();

		map.put("totalCount", totalCount);

		map.put("list", list);

		return map;
	}

	public void insert(HashMap paramMap) throws Exception {
		paramMap.get("cnvsnName");
		int dupChk = transformDao.selectDupCount(paramMap);
		if (dupChk > 0)
			if (dupChk > 0) throw new Exception("이미 존재하는 변환 매핑코드 입니다. - "+ paramMap.get("cnvsnName"));

		paramMap.put("chngEonot", "1");//0.미사용 1.사용
		paramMap.put("modfiMgtStusDstcd", " ");

		//1.EAI Message에 셋팅
		updateTransfromEaiSvcName(paramMap);
		// 2.EAI
		transformDao.insert(paramMap);

	}

	public void transaction(HashMap paramMap) throws Exception {
		String cnvsnName = (String) paramMap.get("cnvsnName");
		String eaiSvcName = (String) paramMap.get("eaiSvcName");
		String cnvsnDesc = (String) paramMap.get("cnvsnDesc");
		String eaiSevrDStcd = (String) paramMap.get("eaiSevrDStcd");
		String srcLayoutName = (String) paramMap.get("srcLayoutName");
		String tgtLayoutName = (String) paramMap.get("tgtLayoutName");
		String chkForce = (String) paramMap.get("chkForce");
		String cnvsnType = (String) paramMap.get("cnvsnType");
		String useYn = (String) paramMap.get("useYn");
		String verInfo = (String) paramMap.get("verInfo");
		HashMap[] list = (HashMap[]) paramMap.get("list");

		if (chkForce != null && "true".equals(chkForce)) {
			paramMap = new HashMap();
			paramMap.put("cnvsnName", cnvsnName);
			paramMap.put("eaiSvcName", eaiSvcName);
			paramMap.put("cnvsnType", cnvsnType);
			paramMap.put("chngEonot", "1");//0.미사용 1.사용
			updateTransfromEaiSvcName(paramMap);
		}

		paramMap = new HashMap();
		//1.변환 테이블  update
		paramMap.put("cnvsnName", cnvsnName);
		paramMap.put("cnvsnDesc", cnvsnDesc);
		paramMap.put("eaiSevrDStcd", eaiSevrDStcd);
		paramMap.put("useYn", useYn);
		paramMap.put("verInfo", verInfo);
		transformDao.updateTransform(paramMap);
		//2.변환 소스/결과 테이블 update
		paramMap = new HashMap();
		paramMap.put("cnvsnName", cnvsnName);
		transformDao.deleteTransformSourceResult(paramMap);

		//2-1.SRC 등록
		paramMap.put("loutName", srcLayoutName);
		paramMap.put("sourcRsultDstcd", "SRC_LAYOUT");
		transformDao.insertTransformSourceResult(paramMap);

		//2-2.TGT 등록
		paramMap.put("loutName", tgtLayoutName);
		paramMap.put("sourcRsultDstcd", "TGT_LAYOUT");
		transformDao.insertTransformSourceResult(paramMap);

		//3.변환항목 테이블 update
		//-----------------------------------------------------------------------------
		//  임시코드 : 복합거래시 소스레이아웃을 추가로 등록되도록 임시 수정 (2018.06.26)
		//-----------------------------------------------------------------------------
		String layoutName = null;
		HashMap layoutParamMap = new HashMap();
		layoutParamMap.put("cnvsnName", cnvsnName);
		layoutParamMap.put("sourcRsultDstcd", "SRC_LAYOUT");

		HashMap layoutMap = new HashMap();
		// -----------------------------------------------------------------------------

		paramMap = new HashMap();
		paramMap.put("cnvsnName", cnvsnName);
		transformDao.deleteTransformItem(paramMap);

		for (int i = 0; i < list.length; i++) {
			paramMap.put("cnvsnCmdName", list[i].get("CNVSNCMDNAME"));
			paramMap.put("cnvsnRsultItemPathName", list[i].get("CNVSNRSULTITEMPATHNAME"));
			paramMap.put("cnvsnItemBascVal", StringUtils.getStringValue(list[i].get("CNVSNITEMBASCVAL"), ""));
			paramMap.put("cnvsnItemSerno", list[i].get("CNVSNITEMSERNO"));

			transformDao.insertTransformItem(paramMap);
			// -----------------------------------------------------------------------------
			// 임시코드 : 복합거래시 소스레이아웃을 추가로 등록되도록 임시 수정 (2018.06.26)
			// -----------------------------------------------------------------------------
			layoutName = extractLayoutName((String) list[i].get("CNVSNCMDNAME"));
			if (layoutName == null || srcLayoutName.equals(layoutName) || layoutMap.get(layoutName) != null) {
				// Do nothing
			} else {
				layoutParamMap.put("loutName", layoutName);
				transformDao.insertTransformSourceResult(layoutParamMap);
				layoutMap.put(layoutName, layoutName);
			}
			// -----------------------------------------------------------------------------
		}

	}

	private String extractLayoutName(String path) {
		String layoutName = null;
		int sPos = 0;
		int ePos = 0;
		if (path == null || path.length() == 0)
			return null;

		sPos = path.lastIndexOf("(");
		if (sPos < 0) {
			sPos = 0;
		} else if (sPos > 0) {
			sPos = sPos + 1;
		}

		ePos = path.indexOf(".");
		if (ePos < 0)
			sPos = 0;

		if (ePos > 0 && ePos > sPos) {
			layoutName = path.substring(sPos, ePos);
			layoutName = layoutName.trim();
		}
		return layoutName;
	}

	public void delete(String cnvsnName, String eaiSvcName, String cnvsnType) throws Exception {
		HashMap paramMap = new HashMap();
		paramMap.put("eaiSvcName", eaiSvcName);
		paramMap.put("cnvsnName", cnvsnName);
		paramMap.put("cnvsnType", cnvsnType);
		paramMap.put("chngEonot", "0");//0.미사용 1.사용

		//1.delete transform  //TR01 삭제
		transformDao.deleteTransform(paramMap);
		//2.delete transform  //TR02 삭제
		transformDao.deleteTransformSourceResult(paramMap);
		//3.delete transform  //TR03 삭제
		transformDao.deleteTransformItem(paramMap);

		//4.EAI Message에 셋팅
		if (eaiSvcName != null && !"".equals(eaiSvcName)) {
			paramMap.put("cnvsnName", "");
			updateTransfromEaiSvcName(paramMap);
		}

	}

	public void updateTransfromEaiSvcName(HashMap paramMap) {
		String cnvsnType = null;
		HashMap map = new HashMap();
		map.put("eaiSvcName", (String) paramMap.get("eaiSvcName"));
		map.put("svcPrcssNo", "1");

		try {
			HashMap eaiMsgMap = eaiMessageDAO.selectDetail(map);
			HashMap ifc = eaiMessageDAO.selectDetailSvc(map);
			// 기동 : SVCMOTIVUSEDSTCD    수동 : PSVINTFACDSTICNAME

			String motivdstcd = String.valueOf(eaiMsgMap.get("SVCMOTIVUSEDSTCD"));
			String psvindstcd = String.valueOf(ifc.get("PSVINTFACDSTICNAME"));
			if (logger.isInfoEnabled())
				logger.info("motivdstcd :" + motivdstcd + ", psvindstcd : " + psvindstcd);

			if ("ASYN".equals(motivdstcd) && "ASYN".equals(psvindstcd)) {
				if (!"ERR".equals((String) paramMap.get("cnvsnType"))) {
					cnvsnType = "REQ";
					paramMap.put("cnvsnType", cnvsnType);
				}
			}
		} catch (Exception e) {
			logger.error(e.toString());
		}
		transformDao.updateTransfromEaiSvcName(paramMap);
	}

	public List<HashMap> selectTransform(String cnvsnName) {
		HashMap params = new HashMap();
		params.put("cnvsnName", cnvsnName);
		return transformDao.selectTransform(params);
	}

	public void exportData(HashMap paramMap) throws Exception {
		String eaiBzwkDstCd = (String) paramMap.get("eaiBzwkDstCd");
		String userId = (String) paramMap.get("userId");
		String cmId = (String) paramMap.get("cmId");
		String[] arrCnvsnNames = (String[]) paramMap.get("arrCnvsnNames");

		//변환명 중복 제거
		arrCnvsnNames = new HashSet<String>(Arrays.asList(arrCnvsnNames)).toArray(new String[0]);

		Properties prop = monitoringContext.getProperties();
		if (prop == null) {
			throw new Exception("프라퍼티 정보가 없습니다. - CM_CONFIG");
		}
		// [2020-01-08 13:45:54,490] INFO (AuroraUtil.java:134) - addCMResource:
		// 9159|EAI200001|/fslog/eai/cmtemp/eai/EAI200001/DSG/transform/TRANSFORM_EAI_TST0200100EAI_REQ.txt
		String auroraIni = (String) prop
				.getProperty(MonitoringContext.CM_AURORA_INI_PATH, "/fshome/greai/eaiadm/aurora/auroraApi_config.ini");
		String localPath = (String) prop.getProperty(MonitoringContext.CM_AURORA_TMP_PATH, "/fslog/eai/cmtemp/");
		String rootPath = localPath + eaiBzwkDstCd.toLowerCase() + File.separator + cmId + File.separator;
		List<String> cmList = new ArrayList<String>();
		//변환파일생성
		for (String cnvsnName : arrCnvsnNames) {
			List<HashMap> listTransform = selectTransform(cnvsnName);
			if (listTransform != null && listTransform.size() > 0) {
				String eaiSevrDstcd = (String) listTransform.get(0).get("EAISEVRDSTCD");
				String eaiSevrName = IoMapLoaderKey.getEaiSevrName(eaiSevrDstcd);

				if ("ALL".equals(eaiSevrName)) {
					for (String sevr : IoMapLoaderKey.getAllEaiSevrName()) {
						eaiSevrName = sevr;
						String subPath = eaiSevrName + File.separator + FileWriteUtil.TRANSFORM + File.separator;
						String path = rootPath + subPath;

						DataSourceType dt = DataSourceContextHolder.getDataSourceType();
						try {
							LinkedHashMap<String, List> tables = loaderService
									.transformDownLoadingForData(dt, path, cnvsnName);
							List<LinkedHashMap> interfaceInfo = ioMapLoaderService
									.interfaceInfoDownLoading(path, cnvsnName, eaiSevrName);
							if (interfaceInfo.size() > 0) {
								tables.put("INTERFACEINFO", interfaceInfo);
							}
							FileWriteUtil.FileWrite(path, cnvsnName + FileWriteUtil.EXT_TXT, tables);
							File f = new File(path + cnvsnName + FileWriteUtil.EXT_TXT);
							if (f.exists()) {
								cmList.add(path + cnvsnName + FileWriteUtil.EXT_TXT);
							}
						} catch (Exception e) {
							throw new BizException("파일 생성에 실패하였습니다. CM 파일 목록이 없습니다.");
						}
					}
				} else {
					String subPath = eaiSevrName + File.separator + FileWriteUtil.TRANSFORM + File.separator;
					String path = rootPath + subPath;

					DataSourceType dt = DataSourceContextHolder.getDataSourceType();
					try {
						LinkedHashMap<String, List> tables = loaderService
								.transformDownLoadingForData(dt, path, cnvsnName);
						List<LinkedHashMap> interfaceInfo = ioMapLoaderService
								.interfaceInfoDownLoading(path, cnvsnName, eaiSevrName);
						if (interfaceInfo.size() > 0) {
							tables.put("INTERFACEINFO", interfaceInfo);
						}
						FileWriteUtil.FileWrite(path, cnvsnName + FileWriteUtil.EXT_TXT, tables);
						File f = new File(path + cnvsnName + FileWriteUtil.EXT_TXT);
						if (f.exists()) {
							cmList.add(path + cnvsnName + FileWriteUtil.EXT_TXT);
						}
					} catch (Exception e) {
						throw new BizException("파일 생성에 실패하였습니다. CM 파일 목록이 없습니다.");
					}
				}
			} else {
				logger.error("returned listTR01 is null : cnvsnName=" + cnvsnName);
			}
		}

		if (cmList == null || cmList.size() == 0) {
			throw new BizException("파일 생성에 실패하였습니다. CM 파일 목록이 없습니다.");
		}

		String groupCoCd = bizDao.selectGroupCoCdByEAIBzwkDstCd(new HashMap() {
			{
				put("eaiBzwkDstCd", eaiBzwkDstCd);
			}
		});
	}

	public HashMap selectListToExcel(HttpServletRequest request, HashMap<String, Object> paramMap) throws Exception {

		List list = transformDao.selectListToExcel(paramMap);

		HashMap map = new HashMap();

		map.put("list", list);

		return map;
	}

	public List selectCnvsnDetailPop(String cnvsnName, String tgt_layout, String src_layout) throws Exception {
		HashMap paramMap = new HashMap();
		paramMap.put("cnvsnName", cnvsnName);
		paramMap.put("loutName", tgt_layout);
		List<HashMap> loutList = transformDao.selectLayoutItems(paramMap);
		List<HashMap> transformList = transformDao.selectTransformItems(paramMap);

		for (HashMap trVo : transformList) {
			for (HashMap layoutVo : loutList) {
				String resultFullPath = (String)trVo.get("CNVSNRSULTITEMPATHNAME");	//변환결과 항목경로
				String loutItemPath = (String)layoutVo.get("LOUTITEMPATH");	//실제경로
				if (resultFullPath.endsWith(loutItemPath)) {
					trVo.put("TGTEXIST", "O");
					break;
				} else if (CommonUtil.removeArrayTag(resultFullPath).endsWith(loutItemPath)) {
					trVo.put("TGTEXIST", "O");
					break;
				}
			}
		}
		// º¯È¯ ¸í·É
		HashMap paramMap2 = new HashMap();
		paramMap2.put("cnvsnName", cnvsnName);
		paramMap2.put("loutName", src_layout);
		List<HashMap> loutList2 = transformDao.selectLayoutItems(paramMap2);
		String patternStr = src_layout+".[ㄱ-ㅎ가-Ra-zA-Z0-9_\\-\\.\\[\\]]+";
		Pattern pattern = Pattern.compile(patternStr);

		for (HashMap trVo : transformList) {
			String cnvsnCmdName = (String)trVo.get("CNVSNCMDNAME");	//변환명령
			cnvsnCmdName = CommonUtil.removeArrayTag(cnvsnCmdName);	//배열제거
			Matcher match = pattern.matcher(cnvsnCmdName);
			List<String> matchList = new ArrayList<>();
			while (match.find()) {
				matchList.add((String) match.group());
			}
			if (matchList.size() > 0) { //변환명령에 소스레이아웃 path가 있는 경우
				for (int i = 0; i < matchList.size(); i++) {
					for (HashMap layoutVo : loutList2) {
						String loutItemPath = (String) layoutVo.get("LOUTITEMPATH"); //소스레이아웃 실제경로
						if (matchList.get(i).endsWith(loutItemPath)) {
							trVo.put("SRCEXIST", "O");
							break;
						}
					}
				}
			} else {
				//변환명령이 항목경로가아닌 값(ex:ascii2ebcdicx(DEFAULT_VALUE,12)) 인경우  "O"셋팅
				trVo.put("SRCEXIST", "O");
			}
		}

		return transformList;
	}

	public List<String> selectTransformListByLayoutList(List<String> layoutList) {

		HashMap<String, Object> paramMap = new HashMap<>();
		paramMap.put("layoutList", layoutList);

		List<String> result = transformDao.selectTransformListByLayoutList(paramMap);

		if (result == null) {
			/** empty list **/
			return new ArrayList<>();
		}

		return result;
	}
}
