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

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Properties;

import com.eactive.eai.batch.job.jobConstant.TelegramKeys;
import com.eactive.eai.batch.job.jobHandle.JobProcessData;
import com.eactive.eai.batch.job.jobItem.DefaultTelegram;
import com.eactive.eai.batch.job.jobItem.TelegramService;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.secure.inisafe.IniSafeManager;

public class SEND_BOKNG_0310 extends DefaultTelegram implements TelegramService {

//  private int BLOCK_NO;
  private int SEQUENCE_NO;
  private int REAL_BYTE;         // 실 data byte수
  private int SEND_LENGTH;       //TCP/IP전문 송신 BYTES수로 "업무구분코드"이후의 송신할 전문 길이
  private int REAL_SEND_LENGTH;  //실제 송신할 전문의 총길이

  private Properties telegramInfo;
  private byte[] fileData;

  /**
   * 생성자
   */
  public SEND_BOKNG_0310() {
  }

  /**
   * 전문조립
   */
  public boolean doExecute() {
      try {
          boolean result = setBlockAndSeqNO();
          if (!result) {
              return false;
          }
          result = calculateSendLength();
          if (!result) return false;

          //필수 (전문전체길이 - 길이부길이)
          compileField(0, ""+SEND_LENGTH, this.al_FieldProps[0]);
          
          //업무구분코드 - BOK
          compileField(1, telegramInfo.getProperty(TelegramKeys.BIZ_GBN), this.al_FieldProps[1]);
          
          //국고망: 'BOK', 한은망: 'FTP'참가기관 코드
          //- 국고망 : 현행 기관코드(외부기관 지로코드)를 맨 앞에서 
          //3자리 기재 (마지막자리는 공백)
          //- 한은망 : 현행 기관코드(한국은행 부여 기관코드)를 기재
          compileField(2, telegramInfo.getProperty(TelegramKeys.BANK_CODE), this.al_FieldProps[2]);
          
          //전문 목록 상의 전문종별
          compileField(3, this.getFldTelegramType(), this.al_FieldProps[3]);
          
          //거래구분코드 (File Name) 
          compileField(4, batchDoc.getBatchMsg().getHeader().getBizCode(), this.al_FieldProps[4]);
          
          //전문 발생 (송신) 주체, 참가기관 발생: 'B', 한국은행 발생: 'C'
          compileField(5, telegramInfo.getProperty(TelegramKeys.TRA_FLAG_BANK), this.al_FieldProps[5]);
          
          //전문처리결과, 정상: '000', 오류:  'A. 응답코드' 참조
          compileField(6, this.getResolveResponseCode(), this.al_FieldProps[6]);
          // 여기 까지 공통부
          
          //송수신 업무 구분코드.- BOK 중심 수신 구분, 항시 ‘S'
          compileField(7, getFldTrClass() , this.al_FieldProps[7]);

          //Block-NO
          compileField(8, ""+this.batchDoc.getBatchMsg().getBody().getBlockNum() , this.al_FieldProps[8]);

          //Sequence-NO
          compileField(9, ""+SEQUENCE_NO , this.al_FieldProps[9]);

          //Record 수
          int recCnt = this.REAL_BYTE / batchDoc.getBatchMsg().getHeader().getRecLen();
          compileField(10, "" + recCnt, this.al_FieldProps[10]);
          
          if (batchDoc.getBatchMsg().getBody().getMissingNmCount() == 0) { //결번갯수가 0이면 결번데이터 전송 완료
              this.setConditionTxt(TelegramKeys.LOSSEND);
          }

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

  public int getInformalFieldSendData(int idx, byte[] data) {
      try {
          if (idx >= this.getFieldCount() ) {
              logger.debug("{}  getInformalFieldSendData> " +idx+ " is bigger than field count", logHeader);
              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 (data.length < REAL_BYTE) {
              logger.debug("{}  getInformalFieldSendData> InformalFieldSendData size is bigger than buffer size", logHeader);
              String[] msgArgs = new String[2];
              msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
              msgArgs[1] = ""+idx;
              String errCode = "BECEAIFJI014";
              String errMsg = ExceptionUtil.getErrorCode (errCode, msgArgs);
              this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
              return -1;
          }

          byte[] encData = IniSafeManager.getInstance().enc(batchDoc,fileData);
          ByteArrayInputStream bin = new ByteArrayInputStream(encData);
          bin.read(data, 0, REAL_BYTE);
          return REAL_BYTE;
      } catch (Exception ex) {
          String[] msgArgs = new String[1];
          msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
          String errCode = "BECEAIFJI006";
          String errMsg = ExceptionUtil.getErrorCode (ex, errCode, msgArgs);
          this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
          logger.error(ex.getMessage(),ex);
          return -1;
      }
  }

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

			//DB로그에 남길 전문 헤더 설정
          ByteArrayOutputStream baout = new ByteArrayOutputStream();
          for (int i=0; i<7; i++) { 
              baout.write((byte[])this.al_Field.get(i));
          }
          batchDoc.getBatchMsg().setTelegramHeader(new String(baout.toByteArray()));

          //DB로그에 남길 전문 바디 설정
          baout = new ByteArrayOutputStream();
          for (int i=7; i< al_Field.size(); i++) {  
              baout.write((byte[])this.al_Field.get(i));
          }
          batchDoc.getBatchMsg().setTelegramBody(new String(baout.toByteArray()));

          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 boolean doPreExecute() {
      try {
          if (!super.doPreExecute()) return false;

          //BATCH작업구분코드 (processCode)에 따른 프로퍼티 정보 가져오기
          telegramInfo = getTelegramInfo();

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

  /**
   * 실제 송신할 전문의 총길이를 리턴해준다.
   */
  public int getSendLength()
  {
      try {
          return REAL_SEND_LENGTH;  //실 DATA BYTE수
      } catch (Exception e) {
          String[] msgArgs = new String[1];
          msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
          String errCode = "BECEAIFJI013";
          String errMsg = ExceptionUtil.getErrorCode (e, errCode, msgArgs);
          this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
          logger.error(e.getMessage(),e);
          return -1;
      }
  }

  /**
   * 비정형 필드에 대한 송신 길이를 계산해서 리턴해준다.
   *
   * 필드(idx)가 비정형 필드(XX)인지 점검하고 , 해당 필드에 대한 예상 길이를 계산하여 리턴하도록 한다
   *
   * 비정현 필드를 가지고 있는 개별 Telegram Class 에서 오버라이드 필요.
   */
  public int getCalculatedLength(int idx) {
      try {
          if (idx >= this.getFieldCount() ) {
              logger.debug("{} getCalculatedLength> parameter is bigger than field count", logHeader);
              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)) {

             return REAL_BYTE;
          } 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;
          }
      }catch (Exception e) {
          String[] msgArgs = new String[1];
          msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
          String errCode = "BECEAIFJI005";
          String errMsg = ExceptionUtil.getErrorCode (e, errCode, msgArgs);
          this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
          logger.error(e.getMessage(),e);
          return -1;
      }
  }

  private boolean setBlockAndSeqNO ()
  {

	  try {

//          int block_no = this.batchDoc.getBatchMsg().getBody().getBlockNum();

          int missing_count = this.batchDoc.getBatchMsg().getBody().getMissingNmCount();
          String missing_field = this.batchDoc.getBatchMsg().getBody().getMissingNmField();
          int missing_fld_len = missing_field.getBytes().length;
          byte[] _missing = missing_field.getBytes();

//          this.BLOCK_NO = block_no;

          for (int i=0; i<missing_fld_len; i++) { //missing_filed의 길이는 block_size와 동일
              if(_missing[i] == '0') {
            	  this.SEQUENCE_NO = i+1;
            	   _missing[i] = '1';
                  missing_count -= 1;
                  break;
              }
          }
          this.batchDoc.getBatchMsg().getBody().setMissingNmField(new String(_missing));
          this.batchDoc.getBatchMsg().getBody().setMissingNmCount(missing_count);
          
      	  String uuid = this.batchDoc.getBatchMsg().getHeader().getUUID();
          JobProcessData job = JobProcessData.getInstance();
          HashMap<String, Object> hm = job.getBatchStageData(uuid);

          @SuppressWarnings("unchecked")
          HashMap<Integer, byte[]> block_data = (HashMap<Integer, byte[]>)hm.get(JobProcessData.PROCDATA_BLOCKDATA);

          if (block_data == null ){
              logger.debug( logHeader + " : " + ExceptionUtil.getErrorCode("SENDED FILE DATA IS NULL"));
              String[] msgArgs = new String[1];
              msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
              String errCode = "BECEAIFJI026-1";
              String errMsg = ExceptionUtil.getErrorCode (errCode, msgArgs);
              this.batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
              return false;
          }
          byte[] data = (byte[]) block_data.get( new Integer(SEQUENCE_NO -1) );
          this.REAL_BYTE = data.length;
          fileData = new byte[REAL_BYTE];
          System.arraycopy( data,  0, fileData, 0, data.length);

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

  private boolean calculateSendLength () {
      try {
          for (int i=1; i< this.al_Field.size()-1; i++) {
              byte[] aField = (byte[]) this.al_Field.get(i);
              SEND_LENGTH += aField.length;
          }
          SEND_LENGTH += REAL_BYTE;
          REAL_SEND_LENGTH = SEND_LENGTH;
          for (int i=0; i < 1 ; i++) {
              byte[] aField = (byte[]) this.al_Field.get(i);
              REAL_SEND_LENGTH += aField.length;
          }
      } catch (Exception e) {
          String[] msgArgs = new String[1];
          msgArgs[0] = this.batchDoc.getBatchMsg().getHeader().getProcessCode();
          String errCode = "BECEAIFJI025";
          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(6);
    }

}
