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

import com.eactive.eai.adapter.socket.common.CommonLib;
import com.eactive.eai.adapter.socket.config.ConfigurationContext;
import com.eactive.eai.adapter.socket.config.SocketAdapterManager;
import com.eactive.eai.common.util.Logger;
import java.util.HashMap;
import java.util.LinkedList;

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


/**
 * Connection된 모든 Socket에 대한 상태를 관리한다.
 * 업무별 리스트를 관리
 */
public class ConnectionManager extends TimerTask  {

	private HashMap<String, LinkedList<SocketService>>	stateTable;
    private Logger                  logger;
    private long                    lastActivity;

	public ConnectionManager(HashMap<String, LinkedList<SocketService>> state) {
        this.stateTable = state;
        logger          = SocketLogManager.getInstance().getLogger();
        lastActivity    = System.currentTimeMillis();
	}

    // 30분간 미사용 Connection에 대한 강제 CLOSE수행
    // Inbound의 Server Socket Type에 한하여 정리작업을 수행한다.
	public void run() {
        if ( stateTable.size() < 1 ) return;
        long    timeout = SocketAdapterManager.UNUSED_CONNECTION_TIMEOUT;

        if ( !CommonLib.getDate( System.currentTimeMillis() ).equals( CommonLib.getDate( this.lastActivity ) ) ) {
            this.checkActivity();
        }

        if ( timeout < 1 ) return;

        Object[] it = stateTable.values().toArray();

        for ( int k=0; k < it.length; k++ ) {
            try {
                @SuppressWarnings("unchecked")
				LinkedList<SocketService> groupList = (LinkedList<SocketService>) it[k];
                if ( groupList.size() < 1 ) continue;
                Object[]   x = groupList.toArray();

                SocketService connection = (SocketService) x[0];
                if ( connection.getContext().getBoundUsage().equals( ConfigurationContext.INBOUND_SOCKET )
                        && connection.getContext().getSocketType().equals( ConfigurationContext.SERVER_SOCKET ) ) {
                    for ( int i=0; i < x.length; i++ ) {
                        connection  = (SocketService) x[i];
                        if ( connection.idle( timeout ) ) {
                            StringBuffer connInfo = new StringBuffer();

                            connInfo.append("Local Address=");
                            try {
                                connInfo.append( connection.getCurrentSocket().getLocalAddress().getHostAddress()).append(":").append(connection.getCurrentSocket().getLocalPort()).append(", ");
                            } catch( Exception e ) {
                                connInfo.append( "?:?,");
                            }
                            connInfo.append("Remote Address=");
                            try {
                                connInfo.append( connection.getCurrentSocket().getInetAddress().getHostAddress()).append(":").append(connection.getCurrentSocket().getPort());
                            } catch( Exception e ) {
                                connInfo.append( "?:?");
                            }

                            if(logger.isInfoEnabled()){
                                logger.info( CommonLib.getMessage("BICEAIMSA027", new String[]{ Long.toString( timeout/1000 ), connInfo.toString() } )) ;
                            }
                            connection.disconnect();
                            if(logger.isInfoEnabled()){
                                logger.info( CommonLib.getMessage("BICEAIMSA028", new String[]{ connInfo.toString() } )) ;
                            }
                        }
                    }
                }
            } catch( Exception e ) {
                logger.error( CommonLib.getMessage("BECEAIMSA008", new String[]{ e.getMessage() }), e );
            }
        }
	}

    private void checkActivity() {
        Object[] it = stateTable.values().toArray();

        for ( int k=0; k < it.length; k++ ) {
            try {
                @SuppressWarnings("unchecked")
				LinkedList<SocketService> groupList = (LinkedList<SocketService>) it[k];
                if ( groupList.size() < 1 ) continue;
                Object[]   x = groupList.toArray();

                SocketService connection = null;
                for ( int i=0; i < x.length; i++ ) {
                    try {
                        connection  = (SocketService) x[i];
                        connection.checkActivity();
                    } catch( Exception ie ) {}
                }
            } catch( Exception e ) {}
        }
    }

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

        sb.append("\n■ ConnectionManager : ");
        for(Iterator<String> iter = stateTable.keySet().iterator(); iter.hasNext();) {
            Object key = iter.next();
            sb.append("\n    ▣ " + key + " : ");
            for(Iterator<SocketService> iter2 = (stateTable.get(key)).iterator(); iter2.hasNext();) {
                sb.append("\n        ● " + iter2.next() + " : ");
            }
        }

        return sb.toString();
    }
}
