package com.eactive.eai.adapter.socket.service;

import com.eactive.eai.adapter.socket.common.CommonLib;
import com.eactive.eai.common.util.Logger;

import java.util.TimerTask;
import java.util.Iterator;
import java.util.LinkedList;


/**
 * Client Socket mode로 사용되는 connection 장애 시 일정간격으로 Recovery를 시도한다.
 * Only 1 thread가 처리한다.
 */
public class RecoveryManager extends TimerTask  {

	private LinkedList<SocketService>    errorTable;
	private Logger                       logger  = SocketLogManager.getInstance().getLogger();

	public RecoveryManager(LinkedList<SocketService> errorTable) {
        this.errorTable	= errorTable;
	}

	public void run() {

        if ( errorTable.size() > 0 ) {
            if(logger.isInfoEnabled()){
                logger.info( CommonLib.getMessage("BICEAIMSA029", new String[]{ Integer.toString( errorTable.size() )} ) );
            }
            retryTheConnect();
        }
	}

	public void retryTheConnect() {

        int count = errorTable.size();

        SocketService aService = null;
		for ( int i=0; i < count; i++) {
			try {
				aService = ( SocketService ) errorTable.removeFirst();
                if ( !aService.isActive() ) continue;
				if ( aService.connect() ) {
					InboundClient client = ( InboundClient )aService;
					client.notifyRecoverConnection();

					try {
	                    StringBuffer connInfo = new StringBuffer();
	                    connInfo.append("Local Address=");
	                    connInfo.append( aService.getCurrentSocket().getLocalAddress().getHostAddress()).append(":").append(aService.getCurrentSocket().getLocalPort()).append(", ");
	                    connInfo.append("Remote Address=");
	                    connInfo.append( aService.getCurrentSocket().getInetAddress().getHostAddress()).append(":").append(aService.getCurrentSocket().getPort());

	                    if(logger.isInfoEnabled())
	                        logger.info( CommonLib.getMessage("BICEAIMSA030", new String[]{ aService.getContext().getAdapterName(), connInfo.toString() }) );
					} catch (Throwable t) {
						logger.error(t.getMessage(),t);
					}
				} else {
					// 에러 복구에 실패하면 로깅하도록 변경. 2009.01.09  정동한
					logger.warn("[RecoveryManager:retryTheConnect]에러 복구 실패[" + aService.getContext().getAdapterName() + "]");
					errorTable.add( aService );
				}
			} catch ( Throwable t ) {
				//if ( aService != null  && aService instanceof SocketService ){
				if ( aService != null){// 20250910 npe
					errorTable.add( aService );
				}
				continue;
			}
		} // trying to reconnect in errorTable...
	}

    public String toString() {
        StringBuffer sb = new StringBuffer();

        sb.append("\n■ RecoveryManager : ");
        for(Iterator<SocketService> iter = errorTable.iterator(); iter.hasNext();) {
            sb.append("\n    ▣ " + iter.next() + " : ");
        }

        return sb.toString();
    }
}
