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

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;

import com.eactive.eai.batch.common.CalendarUtil;
import com.eactive.eai.batch.common.FileUtil;
import com.eactive.eai.batch.common.LogUtil;
import com.eactive.eai.batch.common.StringUtil;
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.osd.OutsideManager;
import com.eactive.eai.batch.osd.OutsideVO;
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_CFABT_0200 extends DefaultTelegram implements TelegramService
{

    private int INFORMALFIELD_INDEX = 14;
    private ByteArrayOutputStream bout;
    private FileOutputStream fout;
    /**
     * 생성자
     */
    public RECV_CFABT_0200() {
        //DATA전문
        bout = new ByteArrayOutputStream();
    }

    /**
     * 전문 해체하기
     */
    public boolean doExecute() {
        if (!super.doExecute()) return false;
        
        String fName = new String((byte[])this.al_Field.get(4)).trim();
        //파일명으로 부터 거래 구분 코드 추출
        int bizCodeStartIndex = 0;
        int bizCodeEndIndex   = 0;
        String processCode = batchDoc.getBatchMsg().getHeader().getProcessCode();
        String institutionCode = batchDoc.getBatchMsg().getHeader().getInstitutionCode();
        ArrayList<OutsideVO> organList = OutsideManager.getInstance().getOutsideInfo(processCode);
        for (int i=0; organList!=null && i<organList.size(); i++) {
            OutsideVO organInfo = organList.get(i);
            if ( institutionCode.equals(organInfo.getOsdCode()) ) {
                bizCodeStartIndex = organInfo.getBizCdStartIdx();
                bizCodeEndIndex   = organInfo.getBizCdEndIdx();
                break;
            }
        }
        if (bizCodeStartIndex <= 0 || bizCodeStartIndex >= fName.length()) bizCodeStartIndex = 0;
        if (bizCodeEndIndex   <= 0 || bizCodeEndIndex   >  fName.length()) bizCodeEndIndex = fName.length();
        String bizCode = fName.substring(bizCodeStartIndex, bizCodeEndIndex);
        batchDoc.getBatchMsg().getHeader().setBizCode(bizCode);

        BatchJobInfoVO bJobInfo = DirInfoManager.getInstance().getFileInfoByDstcd(processCode, bizCode);

        String pattern = null;
        long recLen = 0;
        if ( bJobInfo!= null ){
            pattern = bJobInfo.getSndrcvFileName();
            recLen = bJobInfo.getFileRecSize();
        }
        String recvFileName = FileUtil.getRecvFileName(fName, pattern, batchDoc, true);
        batchDoc.getBatchMsg().getHeader().setFileName(recvFileName);
        batchDoc.getBatchMsg().getHeader().setRecLen((int)recLen);
        
        return true;
        

    }

    public boolean doPostExecute() {
        if (!super.doPostExecute()) return false;
        try {
			//DB로그에 남길 전문 헤더 설정
            ByteArrayOutputStream baout = new ByteArrayOutputStream();
            for (int i=0; i<14; i++) {
                baout.write((byte[])this.al_Field.get(i));
            }
            batchDoc.getBatchMsg().setTelegramHeader(new String(baout.toByteArray()));

            //DB로그에 남길 전문 바디 설정
//            batchDoc.getBatchMsg().setTelegramBody(new String((byte[])this.al_Field.get(14)));
            batchDoc.getBatchMsg().setTelegramBody("");
            batchDoc.getBatchMsg().getBody().setRecvFld01(new String((byte[])this.al_Field.get(1)));
            batchDoc.getBatchMsg().getBody().setRecvFld04(new String((byte[])this.al_Field.get(4)));
            batchDoc.getBatchMsg().getBody().setRecvFld07(new String((byte[])this.al_Field.get(7)));
            batchDoc.getBatchMsg().getBody().setRecvFld08(new String((byte[])this.al_Field.get(8)));
            batchDoc.getBatchMsg().getBody().setRecvFld09(new String((byte[])this.al_Field.get(9)));

            return writeToFile();

        } 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;
        }
    }

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

    /**
     * int getCalculatedLength(int idx)
     * --------------------------------------------------------------------------------------
     * 전달된 인덱스 idx는 비정형 필드여야 한다. 즉 필드의 길이값이 FILE_NO_LENGTH("XX") 이어야 한다.
     * 해당 비정형 필드에 대해 실질적인 전문길이를 동적으로 계산해 낸다.
     * SEND : 송신 길이 계산
     * RECV : 수신 길이 계산
     */
    public int getCalculatedLength(int idx) {
        if (idx >= this.getFieldCount()) {
            String[] msgArgs = new String[2];
            msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
            msgArgs[1] = ""+idx;
            String errCode = "BECEAIFJI011";
            String errMsg = ExceptionUtil.getErrorCode (errCode, msgArgs);
            this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);

            return -1;
        }
        if (this.getFieldLength(idx).equalsIgnoreCase(TelegramService.FIELD_NO_LENGTH)) {
            try {
                String byte_size = new String ((byte[]) al_Field.get(0));
                logger.info("{} the sum of definite field length [" + byte_size + "]", logHeader);
                int preLen = 0;
                for (int inx = 1; inx < idx; inx++) {
                    byte[] aField = (byte[]) this.al_Field.get(inx);
                    preLen += aField.length;
                }
                return Integer.parseInt(byte_size) - preLen;
            } catch (Exception ex) {
                this.batchDoc.getBatchMsg().getBody().setErrorMsg(ex.toString());
                return -1;
            }
        } else {

            String[] msgArgs = new String[2];
            msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
            msgArgs[1] = ""+idx;
            String errCode = "BECEAIFJI012";
            String errMsg = ExceptionUtil.getErrorCode (errCode, msgArgs);
            this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);

            return -1;
        }
    }

    public boolean doInformalField(int idx, byte[] data, int length)
    {
        try {
            if (idx == INFORMALFIELD_INDEX) {
            	bout.write(data, 0, length);
            } else {
                logger.debug("{} doInformalField >> index of informal action error : " + idx, logHeader);

                String[] msgArgs = new String[2];
                msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
                msgArgs[1] = ""+idx;
                String errCode = "BECEAIFJI012";
                String errMsg = ExceptionUtil.getErrorCode (errCode, msgArgs);
                this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);

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

    public boolean doPreExecute() {
        try {
            if (!super.doPreExecute()) return false;
            return true;
        } catch (Exception ex) {
            String[] msgArgs = new String[1];
            msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
            String errCode = "BECEAIFJI003";
            String errMsg = ExceptionUtil.getErrorCode (ex, errCode, msgArgs);
            this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
            logger.error( ex.getMessage(), ex);
            return false;
        }
    }

    private boolean writeToFile(){
    	if ( !createFile () )
    		return false;
		boolean isHeader = false;
		boolean isTrailer = false;
		int recLen = batchDoc.getBatchMsg().getHeader().getRecLen();
		try {
            String strRecvLen = getJobInfo().getProperty(TelegramKeys.RECV_REC_LEN);
            recLen = Integer.parseInt(strRecvLen);
		} catch (Exception e) {}

		byte[]layout = new byte[recLen];
		try {
			int recCnt = Integer.parseInt( super.getFieldValueString(9) );
			for (int jnx = 0; jnx < recCnt; jnx++) {
	    		System.arraycopy( bout.toByteArray(), jnx*layout.length, layout,0,layout.length);
	            fout.write(layout);
	            fout.write( '\n' );
	            long lnCurSize = batchDoc.getBatchMsg().getBody().getCurFileSize()+recLen;
	            batchDoc.getBatchMsg().getBody().setCurFileSize(lnCurSize);
	            batchDoc.getBatchMsg().getHeader().setFileSize(lnCurSize);
	            byte[] hdata = new byte[2];
	            if ( layout.length > 2 ){
	            	System.arraycopy(layout, 0, hdata, 0, 2);
	            	if ( "HD".equals(new String(hdata))){
	            		isHeader = true;
	            		batchDoc.getBatchMsg().getHeader().setTotRecCnt(0);
	            	}
	            	if ( "TD".equals(new String(hdata))){
	            		isTrailer = true;
	            	}
	            }
			}
			int curCnt = (int)batchDoc.getBatchMsg().getHeader().getTotRecCnt();
			batchDoc.getBatchMsg().getHeader().setTotRecCnt(curCnt + recCnt);
		} catch (Exception e) {
			logger.error( e.getMessage(), e);
			return false;
		}finally{
			try {
				fout.close();
			} catch (Exception e2) {
				logger.error( e2.getMessage(), e2);
			}
		}
		
		try {
			if ( isHeader ){
				batchDoc.getBatchMsg().setFileHeader(new String(layout));
				LogUtil.setLogFileStart(batchDoc);
			}
			if ( isTrailer ){
				//File 종료시간 설정
				batchDoc.getBatchMsg().getBody().setPhaseEndTime(CalendarUtil.getCurrentTimeNoDash());
				//DB로그에 남길 파일 헤더,트레일러 내용 설정
				batchDoc.getBatchMsg().setFileTrailer(new String(layout));

	            String strFullPath = batchDoc.getBatchMsg().getHeader().getFilePath();
	            if (strFullPath.charAt(strFullPath.length()-1) != File.separatorChar) {
	                strFullPath = strFullPath + File.separator;
	            }
	            strFullPath = strFullPath + batchDoc.getBatchMsg().getHeader().getFileName();
	            File file = new File(strFullPath);
				File rcvArchFile = new File( StringUtil.realToArchDir(strFullPath) );
				File rcvRootFile = new File( StringUtil.realToRootDir(strFullPath) );

				boolean isSuccessMoveFile = file.renameTo(rcvArchFile);
				if (!isSuccessMoveFile) {
					String errMsg = ExceptionUtil.getErrorCode("BECEAIFJI030", new String[] {file.getAbsolutePath(), rcvArchFile.getAbsolutePath()});
					batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);	//수신 파일을 수신 Real 디렉토리에서 수신 Arch 디렉로 이동시 오류가 발생하였습니다. [Real Path: {1}] [Arch Path: {2}]
		            this.setResolveResponseCode("40");
				}
				//수신 Root 디렉토리에 동일 파일명의 0 byte 의 Dummy 파일 생성
				logger.info("{} >>>>> 수신 파일과 동일 파일명의 0 Byte 파일을 Root 디렉토리에 생성......(업무 서버에 자동 송신하도록 수신 File Event 발생)", logHeader);
				if (!rcvRootFile.createNewFile()) {
					String errMsg = ExceptionUtil.getErrorCode("BECEAIFJI031", new String[] {rcvRootFile.getAbsolutePath()});
					batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);	//수신 Root 디렉토리에 0 Byte 파일을 생성할 수 없습니다. [Path: {1}]
		            this.setResolveResponseCode("40");
				}
				LogUtil.setLogFileEnd(batchDoc);
			}
		} catch (Exception e) {
			logger.error( e.getMessage(), e);
			return false;
		}

    	return true;
    }
    private boolean createFile () {
        try {
			String fileName = batchDoc.getBatchMsg().getHeader().getFileName();
            String strFullPath = batchDoc.getBatchMsg().getHeader().getFilePath();
            if (strFullPath.charAt(strFullPath.length()-1) != File.separatorChar) {
                strFullPath = strFullPath + File.separator;
            }
            strFullPath = strFullPath + fileName;
            File file = new File(strFullPath);
            if ( batchDoc.getBatchMsg().getBody().getCurFileSize() > 0 ){
                fout = new FileOutputStream(file, true);   //bytes will be written to the end of the file rather than the beginning
            }else{
                fout = new FileOutputStream(file, false);
            }
        } catch (Exception e) {
            String[] msgArgs = new String[1];
            msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
            String errCode = "BECEAIFJI028";
            String errMsg = ExceptionUtil.getErrorCode (e, errCode, msgArgs);
            this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
            logger.error( e.getMessage(), e);
            return false;
        }
        return true;
    }



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