package com.kbstar.eai.common.loader;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalField;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;

import com.eactive.eai.common.util.StringUtil;
//import com.penta.scpdb.ScpDbAgent;

/** 
* 1. 기능 : 거래로그 파일을 DB에 저장 
* 2. 처리 개요 : 거래로그 파일을 DB에 저장  
* 3. 주의사항 : 독립모듈로 사용하기 위해 개발 
*
* @author  : 
* @version : v 1.0.0
* @see : 
* @since   : 
*/
public class EAILogFIleLoader {
	
	private String driver = "";
	private String url    = "";
	private String ival   = "";
	private String pval    = "";
	private String tableOwner   = "inst1";
	
	private final String delimeter = "#[|]@";
	private final String EOL = "EOL$$;";
	private final String NEWLINE = "\n";
	private int COL_COUNT = 182;
	
	private int totalCount = 0;
	private int insertCount = 0;
	private int position = 0;
	private int commitSize = 100; // commit size
	
	
	private String logSQL = " INSERT INTO #{LOG_MASTER_TABLE} ( \n"
            //EAI업무공통부
            + "     EAIBZWKDSTCD, MSGDPSTYMS, EAISVCSERNO, LOGPRCSSSERNO, EAISEVRINSTNCNAME, \n"
            + "     EAISVCNAME, SVCHMSEONOT, SVCMOTIVUSEDSTCD, SVCPRCSSDSTICNAME, FLOWCTRLROUTNAME, \n"
            + "     INTGRADSTICNAME, GSTATSVCDSTICNAME, SVCPRCSSNO, SVCBFCLMNLOGYN, STNDMSGUSEYN, \n"
            + "     GSTATSYSADPTRBZWKGROUPNAME, PRSNTMSGIDNAME, RSPNSERRCDNAME, MSGPRCSSYMS, SEVRLOGLVELNO, \n"
            + "     SVCLOGLVELNO, ERREAISVCNAME, DMNDERRCHNGIDNAME, DMNDERRFLDNAME, RSPNSERRCHNGIDNAME, \n"
            + "     RSPNSERRFLDNAME, PSVINTFACDSTICNAME, PSVBZWKSYSNAME, PSVSYSIDNAME, PSVSYSSVCDSTICNAME, \n"
            + "     PSVSYSADPTRBZWKGROUPNAME, FLOVRYN, CHNGYN, CHNGMSGIDNAME, INPTMSGIDNAME, \n"
            + "     BASCRSPNSMSGCMPRCTNT, BASCRSPNSCHNGYN, BASCRSPNSCHNGMSGIDNAME, ERRRSPNSMSGCMPRCTNT, ERRRSPNSCHNGYN, \n"
            + "     ERRRSPNSCHNGMSGIDNAME, NEXTSVCPRCSSNO, OUTBNDROUTNAME, TOUTVAL, CMPENSVCPRCSSNAME, \n"
            + "     SUPPLBZWKDATAYN, KEYMGTMSGCTNT, TRACKASISKEY1CTNT, TRACKASISKEY2CTNT, TRACKASISKEY3CTNT, \n"
            + "     TRACKASISKEY4CTNT, EAIGROUPCODSTCD, PGUID, TRANTYPE, RSPNSCHNGMSGTYPE, \n"
            + "     EAIERRCD, EAIERRCTNT, SEVRGROUPNAME, COMPANYCODE, SPLIZLENGTH, ADPTRINSTICODE, \n"
            //EAI업무개별부
            + "     BZWKDATACTNT, \n"

            //전행통합로그 헤더부
            + "     TRANSTARTYMS, LGINGSYSID, LGINGSYSINSTNCID, LGINGYMS, INTGRALOGGUID, \n"
            + "     INTGRALOGIOMSGSERNO, EAISNDRCVTELGMDSTCD, \n"
            //전행통합로그 공통부
            + "     INTGRALOGTELGMRECVTRANCD, INTGRALOGERRCD, EAILOGKNDDSTCD, EAIBZWKTELGMDSTCD, INTGRALOGCHNLDSTCD, \n"
            + "     INTGRALOGMDIADSTCD, EAIDTALSBZWKCD, INTGRALOGTRANBRNCD, LOGIDIVICGRYVSNNO, INTGRALOGITSMMONITAGETYN, \n"
            + "     INTGRALOGTRANSCRENNO, INTGRALOGUSEREMPID, EAISCOPPERCTNT, \n"
            
            //내부표준전문 헤더부
            + "     CICSTRNCD, INTNLSTELGMLEN, TRANBASEYMD, GUIDNO, TELGMDMNDDSTCD, \n"
            + "    TELGMFMATDSTCD, TELGMVALDYMD, TELGMVSNNO, GNRZTOUTCRTCNMVL, SYSIDNAME, \n"
            + "    OGTRANRCHNLDSTCD,PRCSSTCICSTRNCD,TRANPGROUPCOCD,ISCSENDSYSID, SPAREAREA, \n" 
            
            //내부표준전문 공통부(거래정보)
            + "     GROUPCOCD, TELGMRECVTRANCD, PRCSSRTDTRANCD, SCRENNO, OSIDINSTICD, \n"
            + "    TRANSERNO, INOPARTLDSTCD, CMPXTDMNDDSTCD, SYSOEVIRNDSTCD, ITSMMONITAGETYN, \n"
            + "    TRANPTRNDSTCD, RBNDTRANYN, TERMLWAITRQSTYN, OGTRANRSTRYN, OGTRANGUIDNO, \n"
            
            //내부표준전문 공통부(채널정보)
            + "    BNKCD, TRANBRNCD, FEEPRCSSBRNCD, RELAYCHNLDSTCD, CHNLDSTCD, \n"
            + "   CHNLDBZWKDSTCD, MDIADSTCD, LANGDSTCD, TRMNO, USEREMPID, \n"
            + "   TERMLOPRTRNO, TERMLSPVSRNO, N1STSPVSRBRNCD, N2NDSPVSRBRNCD, N2NDSPVSRTRMNO, \n"
            
            //내부표준전문 공통부(입력메시지정보)
            + "     INPTMSGPTRNDSTCD, INPTMSGCTNNYN, INPTMSGSERNO, INPTMSGWRITYMS, \n"
            //내부표준전문 공통부(승인정보)
            + "     ATHORFNSHDSTCD, SPVSRATHORDSTCD, N1STSPVSREMPID, N2NDSPVSREMPID, SPVSRARESNNOITM, \n"
            + "     SPVSRATHORRESNCD, \n"
            //내부표준전문 공통부(전행업무공통부)
            + "     CLSNGAFYN, LSDTTRANYN, IDTREK, BZOPRDDDSTCD, SODBBRNPTRNDSTCD,   \n"
            + "     SODUSERPTRNDSTCD, INOTABILYN, NORTAUSERYN, TRANDSCNDMNDYN, CALLGPGMNAME,   \n"
            + "     RECVLUNAME, CNCLDSTCD, CNCLPTRNDSTCD, TRANCCRESNDSTCD, TRANCCRESNCTNT,   \n"
            + "     OGTRANYMS, CNCLRSTRINFOCTNT, DSCNTRANDSTCD, IDIVIDATAEDTYN, OPBRNCD,  \n" 
            + "     CNCUTISCOPADDR,  \n" 
            //내부표준전문 공통부(출력메시지정보)
            + "     OUTPTDPTRNDSTCD, OUTPTMPTRNDSTCD, OUTPTMSGCTNNYN, OUTPTMSGSERNO, OUTPTMSGWRITYMS,\n"
            + "     BRNCLSNGYN, \n"
            //내부표준전문 공통부(에러정보)
            + "     ERRCD, TREATCD, CNCUTDSCNRQSTYN, FWORKCISCOPADDR, INTFACSENDTRANCD, \n"  
            + "     CNCLECLUDYN, TRSMTRQSTID, CNCLABILYN, OUTPTMDIAEDTNO, ATMCSHRETUNDSTCD,  \n"
            + "     SENDEAISVCNAME, \n"
            + "     LUSNDRCVTYPDSTCD, DTECALLOWTRANYN, IPADDR,  \n"
            
            + "     CHCMNLEN,  MSGCHNLDSTCD, CNTERDSTCD, \n"
            
            + "     SPAREAREA2, TESTCASID,  \n" 
            //내부표준전문 공통부(입력매체부정보)
            + "     INPTMDIAPARTLLEN \n" 
            //내부표준전문 채널공통부
            + "     ,CHANNELCOMMON \n"
            + " ) VALUES ( \n"

            //EAI업무공통부
            + "     ?, ?, ?, ?, ?, \n"	//index to  5
            + "     ?, ?, ?, ?, ?, \n"	//index to 10
            + "     ?, ?, ?, ?, ?, \n"	//index to 15
            + "     ?, ?, ?, ?, ?, \n"	//index to 20
            + "     ?, ?, ?, ?, ?, \n"	//index to 25
            + "     ?, ?, ?, ?, ?, \n"	//index to 30
            + "     ?, ?, ?, ?, ?, \n"	//index to 35
            + "     ?, ?, ?, ?, ?, \n"	//index to 40
            + "     ?, ?, ?, ?, ?, \n"  //index to 45
            + "     ?, ?, ?, ?, ?, \n"	//index to 50
            + "     ?, ?, ?, ?, ?, \n"  //index to 55
            + "     ?, ?, ?, ?, ?, \n"  //index to 60
            + "     ?, \n"  //index to 61
            //EAI업무개별부
            + "     CAST(? AS VARCHAR(1000))||CAST(? AS VARCHAR(1000))||CAST(? AS VARCHAR(1000))||CAST(? AS VARCHAR(1000)), \n"	// 61

            //전행통합로그 헤더부
            + "     ?, ?, ?, ?, ?, \n"	//index to 66
            + "     ?, ?, \n"			//index to 68
            
            //전행통합로그 공통부
            + "     ?, ?, ?, ?, ?, \n"	//index to 68
            + "     ?, ?, ?, ?, ?, \n"	//index to 73
            + "     ?, ?, ?, \n"		//index to 76

            //내부표준전문 헤더부
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?,  \n"	
            
            //내부표준전문 공통부(거래정보)
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            
            //내부표준전문 공통부(채널정보)
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            
            //내부표준전문 공통부(입력메시지정보)
            + "     ?, ?, ?, ?, \n"		
            
            //내부표준전문 공통부(승인정보)
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, \n"				
            
            //내부표준전문 공통부(전행업무공통부)
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, \n"				  
            //내부표준전문 공통부(출력메시지정보)
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, \n"				
            //내부표준전문 공통부(에러정보)
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, ?, ?, \n"	
            + "     ?, ?, ?, ?, ?, \n"	
            + "     ?, \n"			//채널공통부길이 추가
            //내부표준전문 공통부(입력매체부정보)
            + "     ?, \n"				
            // 채널공통부(200)
            + "     ? \n"				
            + " ) ";

	private String logSubSQL = 
     " INSERT INTO #{LOG_SLAVE_TABLE} ( \n"
    + "     EAIBZWKDSTCD, MSGDPSTYMS, EAISVCSERNO, BZWKDATASERNO, LOGPRCSSSERNO \n"
    + "   , BZWKDATACTNT \n"
    + " ) VALUES  (  ?, ?, ?, ?, ? , ? ) ";
    
	private void init(String configPath) throws Exception {
		Properties p = new Properties();
		FileInputStream in = null;
		try{
			in = new FileInputStream(configPath);
			p.load(in);
		} catch (Exception e){
			// System.out.println("환경설정 파일이 없습니다. - 파일명 : " + configPath);
			throw e;
		}
		finally{
			if(in != null) {
				try {
				in.close();
				}
				catch(Exception e) {
					// System.out.println("close error");
				}
			}
		}
	
		driver  = p.getProperty("jdbc.driver");
		url       = p.getProperty("jdbc.url");
		ival     = p.getProperty("jdbc.ivalue");
		tableOwner = p.getProperty("table.owner");	
			
		String iniFilePath    = p.getProperty("ini.file.path");
//		String iniKey         = p.getProperty("ini.key");
		String encpval    = p.getProperty("jdbc.pvalue");
		
		// System.out.println("=========================================================");
		// System.out.println(" EAILogFileLoader Configuration - "+ new Date());
		// System.out.println("=========================================================");
//		System.out.println("driver = " + driver);
//		System.out.println("url = " + url);
//		System.out.println("ivalue = " + ival);
//		System.out.println("pvalue = " + encpval);
//		System.out.println("Table Owner = " + tableOwner);
//		System.out.println("iniFilePath = " + iniFilePath);
		// System.out.println("=========================================================");
		
//		ScpDbAgent agt = new ScpDbAgent();
//		try {
//			pval = agt.ScpDecB64(iniFilePath, "SEC", encpval);
//		}
//		catch(Exception e) {
//			System.out.println("ScpDecB64 error-" +e.toString());
//		}
//		
	}
	
	private static ZonedDateTime get(long time){
		Instant instant = Instant.ofEpochMilli(time);
    	return ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
	}
	
	public static int getDayOfWeekNum(String timeStr) {
		Date date = new Date();
		try {
			date = new SimpleDateFormat("yyyyMMdd").parse(timeStr); // "yyyyMMddHHmmssSSS"
		} catch (ParseException e) {
			// System.out.println("getDayOfWeekNum error - "+timeStr);
//			e.printStackTrace();
		}
		long time = date.getTime(); 
    	ZonedDateTime zdt =  get(time);
    	TemporalField filedISO = WeekFields.of(Locale.KOREA).dayOfWeek();
    	return zdt.getDayOfWeek().get(filedISO);
    }
	
	private int toInt(String s) {
		try {
			return Integer.parseInt(s);
		}
		catch(Exception ex) {
			return 0;
		}
	}
	
	private void loadLog(String cDay, ArrayList list, boolean isForce) throws Exception {
		int insertResult = 0;
		Connection conn = null;
		PreparedStatement preparedStatement = null;
		String[] info = null;
		try	{
			
			// System.out.println(">> Log Date : " + cDay + ", rows=" + list.size());
			
			if( driver != null ) {
				Class.forName(driver);
				conn = DriverManager.getConnection(url, ival, pval);
				conn.setAutoCommit(true);

				int dayOfWeek = getDayOfWeekNum(cDay);
				String tableName = tableOwner+".TSEAILG1" + dayOfWeek;
				String cLogSQL = logSQL.replace("#{LOG_MASTER_TABLE}", tableName);
				
//					System.out.println(cLogSQL);
				preparedStatement = conn.prepareStatement(cLogSQL);
				
				String apndBwkDataYn = "N"; //추가업무데이터 여부
				
				for (int i=0; i<list.size(); i++) {
					info = (String[]) list.get(i);
					try {
						position++;
						totalCount++;
//						System.out.println("column size : " + info.length);
//						for(int p=0; p<info.length;p++) {
//							System.out.println("column ["+p+"] : [" + info[p] +"] -" + info[p].length());
//						}
					
						if(info == null || info.length != COL_COUNT) {
							throw new Exception("파싱데이터에 오류가 있음, 항목갯수 오류("+ info.length+"/"+COL_COUNT+") -  line : "+(i+1));
						}
						int index = 1;
						int info_index = 0;
						apndBwkDataYn = "N"; 
						
						preparedStatement.setString(index++, info[info_index++]);   //EAI업무구분코드
			            preparedStatement.setString(index++, info[info_index++]);   //메시지수신시각
			            preparedStatement.setString(index++, info[info_index++]);  //EAI서비스일련번호
			            preparedStatement.setString(index++, info[info_index++]);  //로그처리일련번호
			            preparedStatement.setString(index++, info[info_index++]); //EAI서버인스탄스명
	
			            preparedStatement.setString(index++, info[info_index++]); //EAI서비스명
			            preparedStatement.setString(index++, info[info_index++]);  //서비스시각유무
			            preparedStatement.setString(index++, info[info_index++]); //서비스동기사용구분코드
			            preparedStatement.setString(index++, info[info_index++]); //서비스처리구분명
			            preparedStatement.setString(index++, info[info_index++]);    //흐름통제라우팅명
			            //index 10
			            
			            preparedStatement.setString(index++, info[info_index++]);  //통합구분명
			            preparedStatement.setString(index++, info[info_index++]);   //기동서비스구분명
			            preparedStatement.setString(index++, info[info_index++]);  //서비스처리번호
			            preparedStatement.setString(index++, info[info_index++]);   //서비스전컬럼로그여부
			            preparedStatement.setString(index++, info[info_index++]);    //표준메시지사용여부
	
			            preparedStatement.setString(index++, info[info_index++]); //기동시스템어댑터업무그룹명
			            preparedStatement.setString(index++, info[info_index++]);    //현재메시지ID명
			            preparedStatement.setString(index++, info[info_index++]);    //응답에러코드명
			            preparedStatement.setString(index++, info[info_index++]);   //메시지처리시각
			            preparedStatement.setString(index++, info[info_index++]);  //서버로그레벨번호
			            //index 20
			            
			            preparedStatement.setString(index++, info[info_index++]);  //서비스로그레벨번호
			            preparedStatement.setString(index++, info[info_index++]);   //오류EAI서비스명
			            preparedStatement.setString(index++, info[info_index++]);   //요청오류변환ID명
			            preparedStatement.setString(index++, info[info_index++]);  //요청에러필드명
			            preparedStatement.setString(index++, info[info_index++]);  //응답오류변환ID명
	
			            preparedStatement.setString(index++, info[info_index++]); //응답에러필드명
			            preparedStatement.setString(index++, info[info_index++]); //수동인터페이스구분명
			            preparedStatement.setString(index++, info[info_index++]);  //수동업무시스템명
			            preparedStatement.setString(index++, info[info_index++]); //수동시스템ID명
			            preparedStatement.setString(index++, info[info_index++]);  //수동시스템서비스구분명
			            //index 30
			            
			            preparedStatement.setString(index++, info[info_index++]);  //수동시스템어댑터업무그룹명
			            preparedStatement.setString(index++, info[info_index++]); //장애극복여부
			            preparedStatement.setString(index++, info[info_index++]);    //변환여부
			            preparedStatement.setString(index++, info[info_index++]); //변환메시지ID명
			            preparedStatement.setString(index++, info[info_index++]); //입력메시지ID명
	
			            preparedStatement.setString(index++, info[info_index++]);    //기본응답메시지비교내용
			            preparedStatement.setString(index++, info[info_index++]);   //기본응답변환여부
			            preparedStatement.setString(index++, info[info_index++]);    //기본응답변환메시지ID명
			            preparedStatement.setString(index++, info[info_index++]);   //오류응답메시지비교내용
			            preparedStatement.setString(index++, info[info_index++]);  //오류응답변환여부
			            //index 40
			            
			            preparedStatement.setString(index++, info[info_index++]);   //오류응답변환메시지ID명
			            preparedStatement.setString(index++, info[info_index++]);    //다음서비스처리번호
			            preparedStatement.setString(index++, info[info_index++]);    //아웃바운드라우팅명
			            preparedStatement.setInt(index++, toInt(info[info_index++]));   //타임아웃값
			            preparedStatement.setString(index++, info[info_index++]); //보상서비스처리명
	
			            preparedStatement.setString(index++, info[info_index++]);    //추가업무데이터여부
			            preparedStatement.setString(index++, info[info_index++]);  //키관리메시지내용
			            preparedStatement.setString(index++, info[info_index++]);   //추적보조키1내용
		                preparedStatement.setString(index++, info[info_index++]);   //추적보조키2내용
		                preparedStatement.setString(index++, info[info_index++]);   //추적보조키3내용
			            //index 50
		                preparedStatement.setString(index++, info[info_index++]);   //추적보조키4내용
			            preparedStatement.setString(index++, info[info_index++]);   // EAI서비스코드의 그룹회사코드
			            preparedStatement.setString(index++, info[info_index++]);   // PGUID
			            preparedStatement.setString(index++, info[info_index++]);   // 거래처리구분코드내용
			            preparedStatement.setString(index++, info[info_index++]);   // 기본에러응답변환여부
			            
		                preparedStatement.setString(index++, info[info_index++]); //EAI에러코드
		                preparedStatement.setString(index++, info[info_index++]); //EAI에러내용
			            preparedStatement.setString(index++, info[info_index++]);	//서버그룹명
			        	preparedStatement.setString(index++, info[info_index++]);	//업체코드, add 20190404
			        	preparedStatement.setInt(index++, toInt(info[info_index++]));	//전문크기, add 20190404
			            //index 60
			            preparedStatement.setString(index++, info[info_index++]);// add 20190404 // adapterNickName
			            
			            // EAI 업무 개별부(4,000bytes)
			            String bizMsgStr = info[info_index++];
			            if(bizMsgStr == null || bizMsgStr.equals(""))
			            	bizMsgStr = " ";
			            
			            String[] bizMsgSplit = StringUtil.chunkStringArray(bizMsgStr, 4000);
			            String bwkData = bizMsgSplit[0];
			            String addBwkData = bizMsgSplit[1];
			            
			            if (!"".equals(addBwkData))
			                apndBwkDataYn = "Y";
			            
			            String[] bwkDataSplit = StringUtil.chunkStringTotal(bwkData, 1000);
	
			            for(int x = 0; x < 4; x++) {    //업무데이터내용 - 59, 60, 61, 62
			                if(bwkDataSplit.length > x)
			                    preparedStatement.setString(index++, bwkDataSplit[x]);
			                else
			                    preparedStatement.setString(index++, "");
			            }
			            
			            // 전행통합로그헤더부(92bytes)
						preparedStatement.setString(index++, info[info_index++]); //채널거래시작일시
						preparedStatement.setString(index++, info[info_index++]);	//로깅시스템ID, 차세대표준화-기술요소 명명규칙참조(mainframe,서버:시스템id)
			            preparedStatement.setString(index++, info[info_index++]);	//로깅시스템인스턴스ID, 차세대표준화-기술요소 명명규칙참조(WAS의 인스턴스)
						preparedStatement.setString(index++, info[info_index++]);	//로깅일시
			            preparedStatement.setString(index++, info[info_index++]);	//GUID번호
			            
			            preparedStatement.setString(index++, info[info_index++]);	//입력메시지일련번호
			            preparedStatement.setString(index++, info[info_index++]);	//송수신전문구분코드
			            
			            // 전행통합로그공통부(131bytes)
			            preparedStatement.setString(index++, info[info_index++]);	//전문수신거래코드
			            preparedStatement.setString(index++, info[info_index++]);	//에러코드
			            preparedStatement.setString(index++,  info[info_index++]);	//로그종류구분코드 - 1.업무로그(정상로그) 2. 업무로그(에러로그), 3. 중계 로그
			            preparedStatement.setString(index++,  info[info_index++]);
			            preparedStatement.setString(index++,  info[info_index++]);	//채널구분코드
			            
			            preparedStatement.setString(index++, info[info_index++]);	//매체구분코드
			            preparedStatement.setString(index++, info[info_index++]);	//세부업무구분코드
			            preparedStatement.setString(index++, info[info_index++]);//거래부점코드
			            preparedStatement.setString(index++, info[info_index++]);
			            preparedStatement.setString(index++, info[info_index++]);	//ITSM모니터링대상여부
			            
			            preparedStatement.setString(index++, info[info_index++]);	//화면번호
			            preparedStatement.setString(index++, info[info_index++]);	//사용자번호
			            preparedStatement.setString(index++, info[info_index++]);	//영역별내용
			            
			            
			            // 내부표준전문 헤더부(73bytes)
			            preparedStatement.setString(index++, info[info_index++]);//CICS트랜젝션코드
			            preparedStatement.setInt(index++, toInt(info[info_index++]) );	//내부표준전문길이
			            preparedStatement.setString(index++, info[info_index++]);	//거래기준년월일
			            preparedStatement.setString(index++, info[info_index++]);	//GUID번호
			            preparedStatement.setString(index++, info[info_index++]);	//전문요청구분코드
			            
			            preparedStatement.setString(index++, info[info_index++]); //전문형식구분코드
			            preparedStatement.setString(index++, info[info_index++]);//전문유효년월일
			            preparedStatement.setString(index++, info[info_index++]);//전문버전번호(TelgmVsnno), add ver.20090128
			            preparedStatement.setInt(index++, toInt(info[info_index++]) );//총괄타임아웃임계치수(GnrzToutCrtcNmvl), add ver.20090128
			            preparedStatement.setString(index++, info[info_index++]);	//SYSID명, add 20090824
	
			            preparedStatement.setString(index++, info[info_index++]);	//중계채널구분코드, add 20090824
			            preparedStatement.setString(index++, info[info_index++]);	//처리대상CICS트랜젝션코드 , add 20101221
			            preparedStatement.setString(index++, info[info_index++]);	//거래처리그룹회사코드, add 20101221
			            preparedStatement.setString(index++, info[info_index++]);	//ISC전송SYSID, add 20200429
			            preparedStatement.setString(index++, info[info_index++]);	//예비 AREA, add 20101221
			            
			            
			            // 내부표준전문 공통부(거래정보, 112bytes)
			            preparedStatement.setString(index++, info[info_index++]);	//그룹회사코드
			            preparedStatement.setString(index++, info[info_index++]);	//전문수신거래코드
			            preparedStatement.setString(index++, info[info_index++]);	//처리결과전문수신거래코드
			            preparedStatement.setString(index++, info[info_index++]);//화면번호
			            preparedStatement.setString(index++, info[info_index++]);	//대외기관코드
			            
			            preparedStatement.setString(index++, info[info_index++]);//거래일련번호
			            preparedStatement.setString(index++, info[info_index++]);	//내외부구분코드
			            preparedStatement.setString(index++, info[info_index++]);	//복합거래요청구분코드
			            preparedStatement.setString(index++, info[info_index++]);	//시스템운영환경구분코드
			            preparedStatement.setString(index++, info[info_index++]);//ITSM모니터링대상여부(ITSMMoniTagetYn), add ver.20090128
	
			            preparedStatement.setString(index++, info[info_index++]);//거래유형구분코드
			            preparedStatement.setString(index++, info[info_index++]);//리바운드 거래여부
			            preparedStatement.setString(index++, info[info_index++]);	//단말대기요구 여부
			            preparedStatement.setString(index++, info[info_index++]);	//원거래복원여부
			            preparedStatement.setString(index++, info[info_index++]);	//원거래 GUID번호
			            
			            //내부표준전문 공통부(채널정보, 47bytes)
			            preparedStatement.setString(index++, info[info_index++]);//은행코드         
			            preparedStatement.setString(index++, info[info_index++]); //거래부점코드     
			            preparedStatement.setString(index++, info[info_index++]);//수수료처리부점코드(FeePrcssBrncd), add ver.20090128
			            preparedStatement.setString(index++, info[info_index++]);//중계채널구분코드 
			            preparedStatement.setString(index++, info[info_index++]); //채널구분코드     
			            
			            preparedStatement.setString(index++, info[info_index++]); //채널세부업무구분코드(ChnlDtalsBzwkDstcd), add ver.20090128
			            preparedStatement.setString(index++, info[info_index++]); //매체구분코드     
			            preparedStatement.setString(index++, info[info_index++]); //언어구분코드     
			            preparedStatement.setString(index++, info[info_index++]); //단말번호         
			            preparedStatement.setString(index++, info[info_index++]); //사용자직원번호   
	
			            preparedStatement.setString(index++, info[info_index++]);//단말조작자번호   
			            preparedStatement.setString(index++, info[info_index++]);//단말책임자번호   
			            preparedStatement.setString(index++, info[info_index++]);//1차책임자부점코드(1stSpvsrBrncd), add ver.20090128
			            preparedStatement.setString(index++, info[info_index++]); //2차책임자부점코드
			            preparedStatement.setString(index++, info[info_index++]);//2차책임자단말번호
	
			            //내부표준전문 공통부(입력메시지정보, 26bytes)
			            preparedStatement.setString(index++, info[info_index++]); //입력메시지유형구분코드
			            preparedStatement.setString(index++, info[info_index++]); //입력메시지계속여부    
			            preparedStatement.setString(index++, info[info_index++]);//입력메시지일련번호    
			            preparedStatement.setString(index++, info[info_index++]); //입력메시지작성일시    
	
			            //내부표준전문 공통부(승인정보, 98bytes)
			            preparedStatement.setString(index++, info[info_index++]); //승인완료구분코드      
			            preparedStatement.setString(index++, info[info_index++]);//책임자승인구분코드    
			            preparedStatement.setString(index++, info[info_index++]);//1차책임자직원번호     
			            preparedStatement.setString(index++, info[info_index++]);//2차책임자직원번호     
			            preparedStatement.setInt(index++,  toInt(info[info_index++]));//책임자승인사유건수
			            
			            preparedStatement.setString(index++,  info[info_index++]); //책임자승인사유코드(10) - 80bytes
			            
			            //내부표준전문 공통부(전행업무공통부, 179bytes)
			            preparedStatement.setString(index++, info[info_index++]);//마감후여부              
			            preparedStatement.setString(index++, info[info_index++]); //전일자거래여부          
			            //index 140
			            preparedStatement.setString(index++, info[info_index++]); //카드거래처리년월일              
			            
			            preparedStatement.setString(index++, info[info_index++]); //영업일구분코드(BzoprDdDstcd), add ver.20090128
			            
			            preparedStatement.setString(index++, info[info_index++]); //SOD영업점유형구분코드
			            
			            preparedStatement.setString(index++, info[info_index++]); //SOD사용자유형구분코드   
			            preparedStatement.setString(index++, info[info_index++]); //입출가능여부            
			            preparedStatement.setString(index++, info[info_index++]); //무자원대체가능사용자여부
			            preparedStatement.setString(index++, info[info_index++]); //거래중단요청여부        
			            preparedStatement.setString(index++, info[info_index++]); //호출프로그램명          
			            
			            preparedStatement.setString(index++, info[info_index++]);//수신LU명                
			            preparedStatement.setString(index++, info[info_index++]); //취소구분코드            
			            //index 150
			            preparedStatement.setString(index++, info[info_index++]); //취소유형구분코드        
			            preparedStatement.setString(index++, info[info_index++]); //거래취소정정사유구분코드
			            
			            preparedStatement.setString(index++, info[info_index++]);//거래취소정정사유내용    
			            
			            preparedStatement.setString(index++, info[info_index++]); //원거래일시
			            
			            preparedStatement.setString(index++, info[info_index++]); //취소복원정보내용(CnclRstrInfoCtnt), add ver.20090128
			            
			            preparedStatement.setString(index++, info[info_index++]);//중단거래구분코드        
			            preparedStatement.setString(index++, info[info_index++]);//개별데이터편집여부      
			            preparedStatement.setString(index++, info[info_index++]); //개설부점코드            
			            
			            preparedStatement.setString(index++, info[info_index++]); //센터컷인터페이스영역주소(CncutIntfacScopAddr), add ver.20090128
			            
			            //내부표준전문 공통부(출력메시지정보, 29bytes)
			            preparedStatement.setString(index++, info[info_index++]); //출력데이터유형구분코드
			            //index 160
			            preparedStatement.setString(index++, info[info_index++]); //출력메시지유형구분코드
			            preparedStatement.setString(index++, info[info_index++]); //출력메시지계속여부    
			            
			            preparedStatement.setString(index++, info[info_index++]);//출력메시지일련번호    
			            preparedStatement.setString(index++, info[info_index++]); //출력메시지작성일시
			            
			            preparedStatement.setString(index++, info[info_index++]); //부점마감여부
			            
			            //내부표준전문 공통부(에러정보, 17bytes)
			            preparedStatement.setString(index++, info[info_index++]);//에러코드            
			            preparedStatement.setString(index++, info[info_index++]); //조치코드            
			            preparedStatement.setString(index++, info[info_index++]); //센터컷 중단요구 여부
			            
			            preparedStatement.setString(index++, info[info_index++]);	//프레임워크제어정보영역주소, add 20090824
			            preparedStatement.setString(index++, info[info_index++]);	//인터페이스송신거래코드, add 20090824
			            //index 170
			            
			            // TODO DB 필드매핑 20101221
			            preparedStatement.setString(index++, info[info_index++]);	//취소제외여부
			            preparedStatement.setString(index++, info[info_index++]);	//전송요구ID
			            preparedStatement.setString(index++, info[info_index++]);	//취소가능여부
			            preparedStatement.setString(index++, info[info_index++]);	//출력매체편집번호
			            preparedStatement.setString(index++, info[info_index++]);	//자동화기기현금반환구분코드
			            preparedStatement.setString(index++, info[info_index++]);//송신EAI서비스명
			            
			            preparedStatement.setString(index++, info[info_index++]);	//LU송수신타입구분
			            preparedStatement.setString(index++, info[info_index++]);	//일자전환허용거래여부
			            preparedStatement.setString(index++, info[info_index++]);	//IP주소
			            
			            preparedStatement.setInt(index++, toInt(info[info_index++]) ); //채널공통부길이
			            
			            preparedStatement.setString(index++, info[info_index++]);	//메시지채널구분코드
			            
			            preparedStatement.setString(index++, info[info_index++]);	//예비 AREA
			            preparedStatement.setString(index++, info[info_index++]);//테스트사례ID
			            
			            //내부표준전문 공통부(입력매체부정보, 4bytes)
			            preparedStatement.setInt(index++, toInt(info[info_index++]) ); //입력매체부길이(InptMdiaCgryLen), add ver.20090128
			            
		            	preparedStatement.setString(index++, info[info_index++]); // 채널공통부
			            
		            	insertResult = preparedStatement.executeUpdate();		
						insertCount += insertResult;
						
						if ("Y".equals(apndBwkDataYn)) {
				            addBwkDataSub(conn, info, addBwkData, dayOfWeek); // 업무데이터서브
				        }
//						conn.commit();
					}
					catch(Exception ex) {						
						// System.out.println("ERROR SKIP INSERT - row : "+ position +", Error : " + ex.toString());
//						ex.printStackTrace();
						if(!isForce) throw ex;
					}
				} // for (int i=0; i<list.size(); i++) {
			}
		}
		catch(SQLException se) {
//			if(conn != null) conn.rollback();
			if(info!=null) {
				// System.out.println("ERROR : DB 오류  - " + info.toString());
			}
			else {
				// System.out.println("ERROR : DB 오류  - " + se.toString());				
			}
//			se.printStackTrace();
			throw se;
		}
		catch(Exception e) {
//			if(conn != null) conn.rollback();
			// System.out.println(e.toString());
//			e.printStackTrace();
			throw e;
		}
		finally {
			try {
				if(preparedStatement != null) preparedStatement.close();
			}
			catch (SQLException sqle) {
				// System.out.println("SQLException was thrown: " + sqle.toString());
			}
			try {
				if(conn != null) conn.close();
			}
			catch (SQLException sqle) {
				// System.out.println("SQLException was thrown: " + sqle.toString());
			}
		}
	}
	
	public void addBwkDataSub(Connection conn, String[] info, String subBizMsgStr, int dayOfWeek) throws Exception {

        String subMsgStr = subBizMsgStr;
        int seq = 0;    //업무테이터 일련번호
        PreparedStatement preparedStatement = null;
        try {
        	String tableName = tableOwner+".TSEAILG2" + dayOfWeek;
			String cLogSQL = logSubSQL.replace("#{LOG_SLAVE_TABLE}", tableName);
        	preparedStatement = conn.prepareStatement(cLogSQL);
            do {
                String[] subMsgSplit = StringUtil.chunkStringArray(subMsgStr, 4000);
                String bwkData = subMsgSplit[0];    //업무데이터
                subMsgStr = subMsgSplit[1];
				preparedStatement.setString(1, info[0]);   //EAI업무구분코드
                preparedStatement.setString(2, info[1]);   //메시지수신시각
                preparedStatement.setString(3, info[2]);  //EAI거래일련번호
                preparedStatement.setInt(4, ++seq);    //업무테이터 일련번호(SMALLINT)
                preparedStatement.setString(5, info[3]);  //로그처리일련번호
                preparedStatement.setString(6, bwkData);   //업무데이터내용

                preparedStatement.executeUpdate();	
                
            } while (!"".equals(subMsgStr) && seq < 99);    // TSEAILG02.BzwkDataSerno : NUMBER(2)
            
        } catch(Exception e) {
        	// System.out.println("DB Logging[SLAVE] Failed - " + info[0] + "|" + info[1] + "|" + info[2] +"|seq="+seq);            
            throw e;
        } finally {
            if(preparedStatement != null) {
            	try {
					preparedStatement.close();
				} catch (SQLException e) {					
					// System.out.println("SQLException was thrown: " + e.toString());
				}
            }
        }
    }
	
	private void parse(String filePath) throws Exception {

		ArrayList<String[]> list = new ArrayList<String[]>();
		int count = 0;
		
		BufferedReader br = new BufferedReader(new FileReader(filePath));
        String lineStr = null;
        StringBuffer sb = new StringBuffer();
        String[] codes = null;
        
        boolean dayChanged = false;
        String pDay = null;
        String cDay = null;
        
        int multiLine = 0;
        try {
			while ((lineStr = br.readLine()) != null) {
				if(EOL.equals(lineStr)) {
					codes = split(sb.toString(), delimeter);
					cDay = codes[1].substring(0, 8);
					if(pDay != null) {
						dayChanged = !pDay.equals(cDay);
					}
					if(dayChanged) {
						loadLog(cDay, list, true);
						count = 0;
						list.clear();
					}
					
					pDay = cDay;				
					count++;
					list.add(codes);
					
					if(count % commitSize == 0) {
						loadLog(cDay, list, true);
						count = 0;
						list.clear();
					}
					multiLine = 0;
					sb.setLength(0);
					continue;
				}
				multiLine++;
				if(multiLine > 1) {
					sb.append(NEWLINE);
				}
				sb.append(lineStr);			
	        }
        }
		catch(Exception e) {
			// System.out.println(e.toString());			
		}
		finally {
			try {
				if(br != null) br.close();
			}
			catch(Exception e) {
				// System.out.println(e.toString());			
			}
		}
		if(count > 0) {
			loadLog(cDay, list, true);
		}
		
		// System.out.println(String.format("## FILE=%s, INSERT ROW COUNTS : (%d/%d)", filePath, insertCount, totalCount));
	}
	
	private String[] split(String data, String deli) {
		String[] s = data.split(deli);
		return s;
	}
	
	public void printArrayList(ArrayList list) {
		for(int i=0; i<list.size(); i++) {
			String[] codes = (String[]) list.get(i);
			for(int j=0; j<codes.length; j++) {
				System.out.print(codes[j]);
				System.out.print(";");
			}
			System.out.print("\n");
		}
	}
	/**
	 * 
	 */
	public EAILogFIleLoader() throws Exception  {
		super();
	}
	
	
	private static String getUsage() {
		return "Usage> java " + EAILogFIleLoader.class.getName() + " [Config File Path] [Log File Path]";
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		EAILogFIleLoader loader = null;
		
		// Local Test :  set false
		boolean isReal = false;
		
		String configPath = "C:\\trlog\\EAILogFileLoader.properties"; // args[0];
		String filePath = "C:\\trlog\\tran.log"; //args[1];
		try {
			if(isReal && args.length < 2) {
				// System.out.println(getUsage());
				System.exit(-1);
			}
			
			if(isReal) {
				configPath = args[0];
				filePath = args[1];
			}
			
			// System.out.println("\n## START LOADING Infomation - " + configPath);
			loader = new EAILogFIleLoader();
			loader.init(configPath);
			loader.parse(filePath);
		} catch (Exception e) {
			// System.out.println("ERROR MAIN");
			// System.out.println(e.toString());
			System.exit(-2);
		}
		System.exit(0);
	}

}
