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

import com.eactive.eai.adapter.socket.common.CommonLib;
import com.eactive.eai.adapter.socket.config.RequestDescriptor;
import com.eactive.eai.adapter.socket.config.SocketAdapterManager;

import com.eactive.eai.common.util.Logger;

public class SessionService extends Thread {

    private String          adapterGroupName;
    private boolean         active;
    private boolean         permanent;
    private Logger          logger;
    private static Logger   errLogger = SocketLogManager.getInstance().getErrLogger();
    private InboundControl	control;

    private int             sendCount;
    private int             recvCount;

      public SessionService(String adapterGroupName, boolean permanent, int seq) {
        this.setName( adapterGroupName + "-SESSION-"  + Integer.toString( seq ) );

        this.adapterGroupName   = adapterGroupName;
        this.active             = true;
        this.permanent          = permanent;
        this.logger             = SocketLogManager.getInstance().getLogger( adapterGroupName );
        this.sendCount          = 0;
        this.recvCount          = 0;
    }

    /**
     * @return Returns the adapterGroupName.
     */
    public String getAdapterGroupName() {
        return adapterGroupName;
    }

    /**
    * @param adapterGroupName The adapterGroupName to set.
    */
    public void setAdapterGroupName(String adapterGroupName) {
        this.adapterGroupName = adapterGroupName;
    }

    /**
    * @return Returns the permanent.
    */
    public boolean isPermanent() {
        return permanent;
    }

    /**
    * @param permanent The permanent to set.
    */
    public void setPermanent(boolean permanent) {
        this.permanent = permanent;
    }

//    private int getTraceLevel() {
//        return  this.traceLevel;
//    }

//    private boolean isSyncMode() {
//        return control.isSyncMode();
//    }

    public void run() {
        SocketAdapterManager.getInstance().addSession( this );
        if(logger.isDebugEnabled())
            logger.debug( CommonLib.getMessage("BICEAIASI001", new String[]{ adapterGroupName, Thread.currentThread().getName() }));

    	while ( active ) {
            try {

            	onMessage();
            	if ( control == null ) {
                    continue;
                }
            	doRequest();

            } catch (Exception e) {
                if ( control != null ) {
                    logger.error( CommonLib.getMessage("BECEAIASI005",
                              new String[]{ e.getMessage(),CommonLib.getDumpMessage(control.getRequest()) } ),  e );

                    if ( logger != errLogger ) {
                            errLogger.error( CommonLib.getMessage("BECEAIASI005",
                                  new String[]{ e.getMessage(),CommonLib.getDumpMessage(control.getRequest()) } ),  e );
                    }
                }
            }
        }

    	SocketAdapterManager.getInstance().removeSession( this );

        if(logger.isInfoEnabled())
            logger.info( CommonLib.getMessage("BICEAIASI005", new String[]{ adapterGroupName, Thread.currentThread().getName() }));
        interrupt();
    }

    private synchronized void onMessage() {
    	try {
            if ( this.control == null ) {
                this.wait( 1000 );
            }
    	} catch ( InterruptedException ie ) {}
    }

    public void wakeup() {
        try {
            this.control.wakeup();
        } catch( Throwable e ) {}

        this.control = null;
        SessionManager.getInstance().addSession( this.adapterGroupName, this );
    }

    public synchronized void notifyMessage() {
        //recvCount++;
    	this.notify();
    }

    private void doRequest() {
        this.recvCount++;
        logger.debug("[ELINK]################ <"+ Thread.currentThread().getName() +"> InboundControl 데이터: 길어서 print skip..."); //"+ new String(control.getRequest()));
        RequestDescriptor descriptor = new RequestDescriptor( control );
        //RequestDescriptorTest descriptor = new RequestDescriptorTest( control );
        descriptor.request();

        wakeup();

        this.sendCount++;

    } // end of doRequest()


    public synchronized void shutdown() {
        active    = false;

        notifyAll();

        interrupt();

    }

    public void setControl(InboundControl control) {
        this.control = control;

    }

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

        strBuff.append( this.getName() ).append("[ RecvCount = ").append( recvCount )
        .append(" SendCount = ").append( sendCount ).append(" ]");

        return strBuff.toString();
    }
}
