package com.eactive.eai.adapter.wca.data;

import java.util.LinkedList;
import java.util.NoSuchElementException;

/** 
* 1. 기능 : EAI Outbound 송수신 데이타 Queue
* 2. 처리 개요 : 
* 3. 주의사항
*
* @author  : 
* @version : v 1.0.0
* @see : 
* @since   : 2005. 6. 17. 오후 3:22:03
*/
public class WCAQueue {
    /**
     * Queue에 누적된 데이터 카운트
     */
    int			nAccQueueCnt    = 0;
    
    /**
     * 현재 Queue에 존재하는 데이터 카운트    
     */
    int 		nCurrQueueCnt   = 0;
    
    /**
     * 현재 Queue 생성 시간
     */
    public long		lCreateTime = 0;
    
    /**
     * 트랜잭션 타임아웃
     */
    private long		lTimeout	= 0;
    
    /**
     * 트랙잰션 default 타임아웃
     */
    private long		lDefaultTimeout	= 0;
    
    /**
     * 수신 데이타 리스트 
     */
    LinkedList	listQueue       = null; 
    
    /**
     * 송신 데이타 
     */
    byte[]      pSendBuff = null;
    
    /**
     * 송신 데이타 길이
     */
    int         nSendLen  = 0;
    
    /**
     * 트랜잭션 키
     */
    private String		sKey	= null;
    
    private String      sGroupCode = null;
    
    /**
     * 재전송 여부 ("LU가 사용중" 메세지 수신시 다른 LU 그룹 세션으로 데이타 송신한다.)
     */
	boolean		bResendFlag  = false ;
    
    /**
     * DFS 메세지 판단 getDataFromQueue할때 결정
     */
	boolean		bDFSFlag  = false ;
    
    /**
     * Timeout 데이타로 처리할 것인지 판단
     * (response 모드이고 queue에 없는 경우 -> queue에 저장하여 inbound로 처리한다.)
     */
    boolean		bResTimeoutFlag  = false ;

    boolean     isRecvSendOK = false;
    
    /** 
    * 1. 기능 : WCA Queue default Constructor
    * 2. 처리 개요 : 
    * 3. 주의사항 
    **/    
    public WCAQueue() { 
        lCreateTime = System.currentTimeMillis();
        
        nAccQueueCnt = 0;
        nCurrQueueCnt = 0;
        listQueue = new LinkedList();
    }
    
    
    /** 
    * 1. 기능 : WCA Queue Constructor
    * 2. 처리 개요 : 
    * 3. 주의사항 
    * 
    * @param nLen            송신 데이타 길이
    * @param pBuff           송신 데이타 데이타
    **/
    public WCAQueue(int nLen, byte[] pBuff) { 
        lCreateTime = System.currentTimeMillis();
        
        nAccQueueCnt = 0;
        nCurrQueueCnt = 0;
        listQueue = new LinkedList();
        nSendLen = nLen;
        pSendBuff = pBuff;
    }
    
   /** 
    * 1. 기능 : 송신 데이타 반환
    * 2. 처리 개요 :
    * 3. 주의사항 
    * 
    * @return 송신 데이타 
    **/
    public byte[] getSendData() {
        return pSendBuff;
    }
     
    public byte[] getSendHeaderData() {
        byte[] pBuff = new byte[WCAHeader.WCA_HEADER_LEN];       
        
        if (pSendBuff == null) { return null; }
        
        System.arraycopy(pSendBuff, 0, pBuff, 0, WCAHeader.WCA_HEADER_LEN);
        return pBuff;
    }
   /** 
    * 1. 기능 : 트랜잭션 키 설정
    * 2. 처리 개요 :
    * 3. 주의사항 
    * 
    * @param 트랜잭션 키
    **/
    public void setKey(String key) {
		sKey = key;
	}
    
   /** 
    * 1. 기능 : 트랜잭션 키 반환
    * 2. 처리 개요 :
    * 3. 주의사항 
    * 
    * @return 트랜잭션 키
    **/
    public String getKey() {
		return sKey;
	}
    
    public void setGroupCode(String groupCode) {
		sGroupCode = groupCode;
	}
    
    public String getGroupCode() {
		return sGroupCode;
	}
    
    /** 
    * 1. 기능 : 호출 모드 반환
    * 2. 처리 개요 :
    * 3. 주의사항 
    * 
    * @return 호출 모드
    **/
    public char getMode() {
        if (pSendBuff == null) { return WCAHeader.TRAN_MODE_NONRESPONSE.charAt(0); }
        return (char)pSendBuff[WCAHeader.OFFSET_MODE];
    }
    
   /** 
    * 1. 기능 : 재전송 여부 설정 
    * 2. 처리 개요 :
    * 3. 주의사항 
    * 
    * @param 재전송 여부(true : 재전송 yes, false : no)
    **/
	public void setResendFlag(boolean flag) {
		bResendFlag = flag;
	}   
    
    /** 
    * 1. 기능 : 재전송 여부 반환
    * 2. 처리 개요 : 재전송 대상이며 타임아웃이 발생하지 않았을 경우 true 반환한다.
    * 3. 주의사항 
    * 
    * @return 재전송 여부(true : 재전송 yes, false : no)
    **/
	public boolean getResendFlag() {
        if (bResendFlag == true && getRemainedTime() > 0) {
            return true;
        }
		return false;
	}
    
   /** 
    * 1. 기능 : 타임아웃 여부 설정 
    * 2. 처리 개요 :
    * 3. 주의사항 
    * 
    * @param 타임아웃 여부(true : yes, false : no)
    **/
	public void setResTimeoutFlag(boolean flag)	{
		bResTimeoutFlag = flag;
	}   
    
   /** 
    * 1. 기능 : 타임아웃 여부 반환
    * 2. 처리 개요 : 
    * 3. 주의사항 
    * 
    * @return 타임아웃 여부(true : yes, false : no)
    **/
	public boolean getResTimeoutFlag() {
        return bResTimeoutFlag;
	}
    
    public boolean getRecvSendOKFlag() {
        return isRecvSendOK;
	}
    
    public void setRecvSendOKFlag(boolean flag) {
        isRecvSendOK = flag;
	}
	
    /** 
    * 1. 기능 : 타임아웃 설정 
    * 2. 처리 개요 :
    * 3. 주의사항 
    * 
    * @param 타임아웃 시간
    **/
	public void setTimeout(int timeout) {
		lTimeout = (long)(timeout * 1000);
	}
    
    public void setDefaultTimeout(int timeout) {
		lDefaultTimeout = (long)(timeout * 1000);
	}
    
    /** 
    * 1. 기능 : 타임아웃 반환
    * 2. 처리 개요 :
    * 3. 주의사항 
    * 
    * @return 타임아웃 시간
    **/
    public int getTimeout() {
        if (lTimeout == -1L) { return (int)lDefaultTimeout; } 
        return (int)lTimeout;
    }    
    
    /** 
    * 1. 기능 : 남아있는 타임아웃 값 반환
    * 2. 처리 개요 : 
    * 3. 주의사항 
    * 
    * @return 타임아웃 시간
    **/
    public long getRemainedTime() {
        if (lTimeout == 0L) {
			return 0L;
        }
        
		long lCurrentTime = System.currentTimeMillis();
		long lRemainTime = lTimeout - (lCurrentTime - lCreateTime);
		if (lTimeout < 0L || lRemainTime <= 0L) { // 타임아웃 발샐시 - 리턴
			return -1L;
		}
		else {
			return lRemainTime;
		}
	}
    
   /** 
    * 1. 기능 : 수신 데이타 리스트에 추가
    * 2. 처리 개요 : 
    * 3. 주의사항 
    * 
    * @return queueData 수신 데이타 
    **/
    public synchronized int addDataToQueue(WCAQueueData queueData) {
        listQueue.addLast(queueData);        
        return 0;
    }
    
    /**
    * 1. 기능 : 수신 데이타 초기화
    * 2. 처리 개요 : 
    * 3. 주의사항  
    **/
    public synchronized void initRecvData() {
        listQueue.clear();
    }
    
    /**
    * 1. 기능 : 수신 데이타 반환
    * 2. 처리 개요 : 
    * 3. 주의사항  
    * 
    * @return 수신 데이타
    **/
    public synchronized byte[] getDataFromQueue() {
        try {
            WCAQueueData queuedata = null;
            int nTempBuffLen = WCAHeader.WCA_HEADER_LEN; 
            // 길이 계산 
            //-----------------------------------------
            // 2008.03.28 : 홍명준
            // 멀티페이지 처리 오류 수정
            //-----------------------------------------
            for(int i = 0; i < listQueue.size(); i++) {
                queuedata = (WCAQueueData)listQueue.get(i);
                nTempBuffLen += (queuedata.pBuff.length - WCAHeader.WCA_HEADER_LEN) ;
                // System.out.println("getDataFromQueue> " + i + " Size = " + queuedata.pBuff.length);
            }
            
            // System.out.println("getDataFromQueue> nTempBuffLen = " + nTempBuffLen);
            
            byte[] pDataBuff = new byte[nTempBuffLen];
            int nBuffPos = WCAHeader.WCA_HEADER_LEN;
            for (int i = 0; i < listQueue.size(); i++) {
                queuedata = (WCAQueueData)listQueue.get(i);
                
                // System.out.println("getDataFromQueue> " + i + " Copy WCA Header");
                System.arraycopy(queuedata.pBuff, 0, pDataBuff, 0, WCAHeader.WCA_HEADER_LEN);
                
                // System.out.println("getDataFromQueue> " + i + " Copy WCA Data, BuffPos = " + nBuffPos + ", Length = " + (queuedata.pBuff.length - WCAHeader.WCA_HEADER_LEN));
                System.arraycopy(queuedata.pBuff, WCAHeader.WCA_HEADER_LEN, pDataBuff, nBuffPos, queuedata.pBuff.length - WCAHeader.WCA_HEADER_LEN);
                nBuffPos += (queuedata.pBuff.length - WCAHeader.WCA_HEADER_LEN);
            }
          
            return pDataBuff;
        }
        catch (NoSuchElementException ex) {
//            System.out.println("getDataFromQueue> Queue is Empty : "+ ex.toString());
            return null;
        }
        catch (Exception e) {
//            System.out.println("getDataFromQueue> Exception : " + e.toString());
            return null;
        }
    }
    
    /**
    * 1. 기능 : 수신 데이타 수 반환
    * 2. 처리 개요 : 
    * 3. 주의사항  
    * 
    * @return 수신 데이타 수
    **/
    public synchronized int getCurrQueueDataCnt() {
        return listQueue.size();
    }
    
    /** 
    * 1. 기능 : DFS 반환
    * 2. 처리 개요 : DFS 메세지 판단
    * 3. 주의사항 
    * 
    * @return DFS 여부(true : DFS yes, false : no)
    **/
	public boolean getDFSFlag() {
		return bDFSFlag;
	}
	
    /** 
    * 1. 기능 : DFS 설정
    * 2. 처리 개요 : DFS 메세지 설정
    * 3. 주의사항 
    * 
    * @return DFS 여부(true : DFS yes, false : no)
    **/
    /*
	public void setDFSFlag(byte[] pBuff)
	{
        byte[] pDFSBuff = new byte[3];
        if (pBuff.length >= WCAHeader.WCA_HEADER_LEN + 3)        
            System.arraycopy(pBuff, WCAHeader.WCA_HEADER_LEN, pDFSBuff, 0, pDFSBuff.length);
            
        // System.out.println("------> DFS : " + new String(pDFSBuff));
        if((new String(pDFSBuff)).equals(new String(WCADefine.DFS_MSG)))
            bDFSFlag = true;    
        else bDFSFlag = false;
	}
    */
}
