package com.eactive.eai.batch.job.jobItem.insure;

import java.io.File;
import java.io.FileOutputStream;

import com.eactive.eai.batch.job.jobConstant.TelegramKeys;
import com.eactive.eai.batch.job.jobItem.DefaultTelegram;
import com.eactive.eai.batch.job.jobItem.TelegramService;

import com.eactive.eai.batch.common.BatchDirUtil;
import com.eactive.eai.batch.common.CalendarUtil;
import com.eactive.eai.batch.common.LogUtil;
import com.eactive.eai.batch.common.StringUtil;
import com.eactive.eai.batch.rule.dirInfo.BatchJobInfoVO;
import com.eactive.eai.batch.rule.dirInfo.DirInfoManager;
import com.eactive.eai.common.exception.ExceptionUtil;

public class RECV_INSBT_0600  extends DefaultTelegram implements TelegramService
{

    private String strFullPathName = "";
    private FileOutputStream fout = null;
    
    private File rcvRealFile = null;
    private File rcvArchFile = null;
    private File rcvErrorFile = null;

    public RECV_INSBT_0600() {
    }
    
    //============================================================================================================================
    // 호출순서 : doPreExecute() -> getCalculatedLength() -> doInformalField() -> doExecute() -> doValidation() -> doPostExecute()
    //============================================================================================================================

    /**
     * doPreExecute() 부모클래스의 기본 수행을 호출해 준 후, 0600 전문 수신의 특이 사항을 수행한다.
     * 0600 전문의 특이사항은 실질적인 파일 수신시 Write할 파일을 열어주는 것이다. (FileOutputStream)
     */
    public boolean doPreExecute()
    {
        if (!super.doPreExecute())  return false;
        return true;
    }

    public boolean doPreExecuteAfterCopy()
    {
        if (!super.doPreExecuteAfterCopy()) return false;

		//1. 파일명 필드 값 체크
		logger.info("{} >>>>> 수신 전문의 '파일명' 전문필드 값 Checking......", logHeader);
		String bizCode            = new String((byte[])al_Field.get( 8)).trim();  //거래구분코드
		String fileName           = new String((byte[])al_Field.get(19)).trim();  //파일명
        
        batchDoc.getBatchMsg().getHeader().setFileName(fileName);  //배치메시지에 파일명 설정

        String processCode   = batchDoc.getBatchMsg().getHeader().getProcessCode();
        
        //2. 수신파일 저장 경로 설정
        //저장 디렉토리는 Inbound Server 에서 설정됨 (응답수신 Real 또는 응답송신 Real)
        this.strFullPathName = batchDoc.getBatchMsg().getHeader().getFilePath();
        String dirDelimiter  = StringUtil.getDirDelimiter(this.strFullPathName);
        if (!this.strFullPathName.endsWith(dirDelimiter)) this.strFullPathName += dirDelimiter;
        
 
		//3. 거래구분코드에 대한 작업구분코드 설정
		BatchJobInfoVO jobInfo = DirInfoManager.getInstance().getFileInfoByDstcd(processCode, bizCode);
        logger.info("{} 거래구분코드 : ["+ bizCode +"]", logHeader);
		if (jobInfo == null) {
			String errMsg = ExceptionUtil.getErrorCode("BECEAIFJI040", new String[] {fileName, processCode, bizCode});
			batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);	//수신 파일 [{1}] 에 해당하는 JOB_CODE를 찾을수 없습니다. [ProcessCode: {2}] [BizCode: {3}]
			super.setResolveResponseCode(TelegramKeys.RPS_HDB_RET_CODE_OTHER_ERROR);
			return false;
		}
        logger.info("{} 작업구분코드 : ["+ jobInfo.getMsgDstCode() +"]", logHeader);
        batchDoc.getBatchMsg().getHeader().setBizCode(bizCode);
		batchDoc.getBatchMsg().getHeader().setJobCode(jobInfo.getMsgDstCode());
		batchDoc.getBatchMsg().getHeader().setRecLen((int)jobInfo.getFileRecSize());
       
       

        this.strFullPathName += fileName;
        logger.info("{}  응답수신 파일 저장 경로 : [" + this.strFullPathName + "]", logHeader);
		rcvRealFile  = new File( this.strFullPathName );  //응답수신_Real 또는 응답송신_Real 디렉토리
		try {
			rcvArchFile  = new File( StringUtil.replaceStr(this.strFullPathName, BatchDirUtil.getResponseRealDir(), BatchDirUtil.getResponseArchDir()) );
			rcvErrorFile = new File( StringUtil.replaceStr(this.strFullPathName, BatchDirUtil.getResponseRealDir(), BatchDirUtil.getResponseErrorDir()) );
		} catch (Exception e) {
			logger.error( e.getMessage(), e);
		}
        
        
        //7. 응답수신 파일 생성
		logger.info("{} >>>>> 응답수신 파일 생성...... ("+ this.strFullPathName +")", logHeader);
        try {
            fout = new FileOutputStream(rcvRealFile);
        } catch (Exception ex) {
            logger.error("{} ★★★★★ 응답수신 파일 생성 시 오류 발생 !! ★★★★★", logHeader, ex);
			String errMsg = ExceptionUtil.getErrorCode(ex, "BECEAIFJI041", new String[] {rcvRealFile.getAbsolutePath()});
			batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);  //수신 파일을 해당 경로에 생성시 오류가 발생하였습니다. [Path : {1}]
			super.setResolveResponseCode(TelegramKeys.RPS_HDB_RET_CODE_OTHER_ERROR);  //기타오류
			return false;
        }
        

        //8. 응답수신 파일 Start DB로그
		logger.info("{} >>>>> 응답수신 파일 Start DB로그......", logHeader);
        try {
            LogUtil.setLogFileStart(batchDoc);
        
        } catch (Exception ex) {
            logger.error("{} ★★★★★ 응답수신 파일 Start DB로그 수행시 오류 발생 !! ★★★★★", logHeader, ex);
			String errMsg = ExceptionUtil.getErrorCode(ex, "BECEAIFJI021", new String[] {processCode});
			batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
			super.setResolveResponseCode(TelegramKeys.RPS_HDB_RET_CODE_OTHER_ERROR);  //기타오류
			return false;
        }

        return true;
    }

    /**
     * int getCalculatedLength(int idx)
     * --------------------------------------------------------------------------------------
     * 전달된 인덱스 idx는 비정형 필드여야 한다. 즉 필드의 길이값이 FILE_NO_LENGTH("XX") 이어야 한다.
     * 해당 비정형 필드에 대해 실질적인 전문길이를 동적으로 계산해 낸다.
     * SEND : 송신 길이 계산
     * RECV : 수신 길이 계산
     */
    public int getCalculatedLength(int idx) {

        try {
            int nDefiniteLength = 0;
            //퇴직연금에서는 마지막에 define 되어 있는 것으로 한다.
            for (int i=0; i< this.al_Field.size()-1; i++) {
                byte[] aField = (byte[]) this.al_Field.get(i);
                nDefiniteLength += aField.length;
            }
            logger.info("{} INFORMAL 필드 이전에 읽어들인 Byte Length : [" + nDefiniteLength + "]", logHeader);

            String strLength = super.getFieldValueString(batchDoc.getBatchMsg().getPhaseinfo().getLengthFieldIndex()-1);
            logger.info("{} HEADER 의 '전문길이' 필드 값 : [" + nDefiniteLength + "]", logHeader);
            
            int nTotalLength = Integer.parseInt(strLength);
            batchDoc.getBatchMsg().getHeader().setFileSize(nTotalLength - nDefiniteLength);  //파일사이즈 설정 (전송 진행상태 확인용)
            logger.info("{} INFORMAL 필드에서 읽어들일 Byte Length : [" + (nTotalLength - nDefiniteLength) + "]", logHeader);
            return (nTotalLength - nDefiniteLength);
            
        } catch (Exception ex) {
            logger.error("{} ★★★★★ 수신 파일 사이즈 계산 시 오류 발생 !! ★★★★★", logHeader, ex);
            this.batchDoc.getBatchMsg().getBody().setErrorMsg(ex.toString());
            return -1;
        }
    }

    public boolean doInformalField(int idx, byte[] data, int length)
    {
        try {
            //파일 끝에 append
            fout.write(data, 0, length);
            
            //읽어 들인 파일 사이즈 저장
            long lnCurSize = batchDoc.getBatchMsg().getBody().getCurFileSize() + length;
            batchDoc.getBatchMsg().getBody().setCurFileSize(lnCurSize);
            
            return true;
                
        } catch (Exception ex) {
            logger.error("{} ★★★★★ 수신 파일 데이터 WRITE 시 오류 발생 !! ★★★★★", logHeader, ex);
            this.batchDoc.getBatchMsg().getBody().setErrorMsg(ex.toString());
            return false;
        }
    }

    public boolean doExecute() {
        if (!super.doExecute())  return false;
		return true;
    }

    /**
     * 전문 Validation
     */
    public boolean doValidation()
    {
        if (!super.doValidation()) return false;
        return true;
    }

    public boolean doPostExecute() {
        if (!super.doPostExecute()) return false;

		try {
            //1. 수신 파일 Close ===========================================================
            if (fout != null) fout.close();

			//2. 수신 파일 End DB로그 ======================================================
            //수신 파일 (Real 디렉토리)
            if (rcvRealFile.exists()) {
                //DB로그에 남길 파일 사이즈 설정
                batchDoc.getBatchMsg().getHeader().setFileSize(rcvRealFile.length());
                try {
                	int recLen = batchDoc.getBatchMsg().getHeader().getRecLen();
					batchDoc.getBatchMsg().getHeader().setTotRecCnt(rcvRealFile.length()/recLen);
				} catch (Exception e) {
					batchDoc.getBatchMsg().getHeader().setTotRecCnt(1);
				}
                //DB로그에 남길 파일 헤더,트레일러 내용 설정
                super.setFileHeaderAndTrailer(rcvRealFile);
            }

			//DB로그에 남길 변경 파일명 설정 (파일명 변경 안함)
			batchDoc.getBatchMsg().getHeader().setRenamedFileName(batchDoc.getBatchMsg().getHeader().getFileName());
			
            //File 종료시간 설정
			batchDoc.getBatchMsg().getBody().setPhaseEndTime(CalendarUtil.getCurrentTimeNoDash());

			//수신 파일 End DB로그
			LogUtil.setLogFileEnd(batchDoc);


			//응답코드가 000 (성공) 이 아니면 Error 디렉토리로 옮기고 리턴
			if ( !super.getResolveResponseCode().equals(TelegramKeys.RPS_HDB_RET_CODE_SUCCESS) ) {
                //3. 수신 파일을 수신 Real 디렉토리 -> 수신 Error 디렉토리로 이동 (파일명 변경 안함)
                logger.info("{} >>>>> 수신 파일을 수신 Real 디렉토리 -> 수신 Error 디렉토리로 이동.....", logHeader);
                boolean isSuccessMoveFile = rcvRealFile.renameTo(rcvErrorFile);
                if (!isSuccessMoveFile) {
                    String errMsg = ExceptionUtil.getErrorCode("BECEAIFJI042", new String[] {rcvRealFile.getAbsolutePath(), rcvArchFile.getAbsolutePath()});
                    if (!batchDoc.getBatchMsg().getBody().getErrorMsg().equals("")) {
                        errMsg += "\n caused by..." + batchDoc.getBatchMsg().getBody().getErrorMsg();
                    }
                    batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);	//수신 파일을 수신 Real 디렉토리에서 수신 Error 디렉로 이동시 오류가 발생하였습니다. [Real Path: {1}] [Error Path: {2}]
                }
                return false;
            }


			//3. 수신 파일을 수신 Real 디렉토리 -> 수신 Arch 디렉토리로 이동 (파일명 변경 안함)
			logger.info("{} >>>>> 수신 파일을 수신 Real 디렉토리 -> 수신 Arch 디렉토리로 이동.....", logHeader);
			boolean isSuccessMoveFile = rcvRealFile.renameTo(rcvArchFile);
			if (!isSuccessMoveFile) {
				String errMsg = ExceptionUtil.getErrorCode("BECEAIFJI030", new String[] {rcvRealFile.getAbsolutePath(), rcvArchFile.getAbsolutePath()});
				batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);	//수신 파일을 수신 Real 디렉토리에서 수신 Arch 디렉로 이동시 오류가 발생하였습니다. [Real Path: {1}] [Arch Path: {2}]
				super.setResolveResponseCode(TelegramKeys.RPS_HDB_RET_CODE_OTHER_ERROR);
				return false;
			}

			logger.info("{} >>>>> 수신 파일과 동일 파일명의 0 Byte 파일을 Root 디렉토리에 생성......(퇴직연금 서버에 자동 송신하도록 수신 File Event 발생)", logHeader);
			try {
				File rcvRootFile = new File( StringUtil.realToRootDir(this.strFullPathName) );
				rcvRootFile.createNewFile();
				if (!isSuccessMoveFile) {
					String errMsg = ExceptionUtil.getErrorCode("BECEAIFJI031", new String[] {rcvRootFile.getAbsolutePath()});
					batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);	//수신 Root 디렉토리에 0 Byte 파일을 생성할 수 없습니다. [Path: {1}]
					super.setResolveResponseCode(TelegramKeys.RPS_HDB_RET_CODE_OTHER_ERROR);
					return false;
				}
			} catch (Exception ex) {
				String errMsg = ExceptionUtil.getErrorCode(ex, "BECEAIFJI031", new String[] { StringUtil.realToRootDir(this.strFullPathName) });
				batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);	//수신 Root 디렉토리에 0 Byte 파일을 생성할 수 없습니다. [Path: {1}]
				super.setResolveResponseCode(TelegramKeys.RPS_HDB_RET_CODE_OTHER_ERROR);
				return false;
			}

			return true;


        } catch(Exception ex) {
            String[] msgArgs = new String[1];
            msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
            String errCode = "BECEAIFJI002";
            String errMsg = ExceptionUtil.getErrorCode (ex, errCode, msgArgs);
            this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
            logger.error( ex.getMessage(), ex);
            return false;
        }
    }

    //---------------- 특정 필드값을 구하는 부분
    // 전문종별코드 필드값 리턴
    public String getTelegramType()
    {
		return super.getFieldValueString(7);
    }
    // 거래구분코드 필드값 리턴
    public String getTrClass()
    {
		return super.getFieldValueString(8);
    }
    //응답코드 필드값 리턴
    public String getResCode()
    {
		return super.getFieldValueString(11);
    }
}