package org.maachang.connector ;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

/**
 * ConnectorManager.
 * 
 * @version 2008/05/25
 * @author masahito suzuki
 * @since MaachangBase 1.00
 */
public class ConnectorManager {
    protected static final int MIN_LENGTH = 5 ;
    protected static final int MAX_LENGTH = 500 ;
    private ArrayList<ConnectorSession> man = null ;
    private ServerSocket server = null ;
    
    private ConnectorManager() {
        
    }
    
    public ConnectorManager( InetAddress addr,int port,int backlog )
        throws Exception {
        if( port <= 0 || port > 65535 ) {
            throw new IllegalArgumentException( "指定ポート番号は不正です" ) ;
        }
        if( backlog <= MIN_LENGTH ) {
            backlog = MIN_LENGTH ;
        }
        else if( backlog > MAX_LENGTH ) {
            backlog = MAX_LENGTH ;
        }
        ServerSocket server = new ServerSocket() ;
        server.setReuseAddress( true ) ;
        server.setSoTimeout( 5000 ) ;
        if( addr == null ) {
            server.bind( new InetSocketAddress( port ),backlog ) ;
        }
        else {
            server.bind( new InetSocketAddress( addr,port ),backlog ) ;
        }
        this.server = server ;
        this.man = new ArrayList<ConnectorSession>() ;
    }
    
    protected void finalize() throws Exception {
        this.destroy() ;
    }
    
    public synchronized void destroy() {
        if( man != null ) {
            int len = man.size() ;
            for( int i = 0 ; i < len ; i ++ ) {
                try {
                    man.remove( 0 ).destroy() ;
                } catch( Exception e ) {
                }
            }
        }
        if( server != null ) {
            try {
                server.close() ;
            } catch( Exception e ) {
            }
        }
        server = null ;
        man = null ;
    }
    
    public synchronized void append( byte[] headerBinary,Socket s ) throws Exception {
        if( isClosed() == true ) {
            if( s != null && s.isClosed() == false ) {
                try {
                    s.close() ;
                } catch( Exception e ) {
                }
            }
            return ;
        }
        if( s == null || s.isClosed() == true ) {
            if( s != null ) {
                try {
                    s.close() ;
                } catch( Exception e ) {
                }
            }
            return ;
        }
        man.add( new ConnectorSession( headerBinary,s ) ) ;
    }
    
    public synchronized void append( ConnectorSession s ) {
        if( isClosed() == true ) {
            return ;
        }
        if( s != null && s.isClosed() == false ) {
            man.add( s ) ;
        }
    }
    
    public synchronized ConnectorSession get( int no ) {
        if( isClosed() == true ) {
            return null ;
        }
        ConnectorSession s = null ;
        try {
            s = man.remove( no ) ;
        } catch( Exception e ) {
            s = null ;
        }
        if( s != null && s.isClosed() == true ) {
            try {
                s.destroy() ;
            } catch( Exception e ) {
            }
            s = null ;
        }
        return s ;
    }
    
    public synchronized void remove( int no ) {
        if( isClosed() == true ) {
            return ;
        }
        ConnectorSession s = null ;
        try {
            s = man.remove( no ) ;
        } catch( Exception e ) {
            s = null ;
        }
        if( s != null && s.isClosed() == false ) {
            s.destroy() ;
        }
    }
    
    public synchronized ServerSocket getServerSocket() {
        if( isClosed() == true ) {
            return null ;
        }
        return server ;
    }
    
    public synchronized int size() {
        if( isClosed() == true ) {
            return -1 ;
        }
        return man.size() ;
    }
    
    public synchronized boolean isClosed() {
        boolean ret = false ;
        try {
            if( man == null || server == null ||
                server.isBound() == false || server.isClosed() == true ) {
                ret = true ;
            }
        } catch( Exception e ) {
            ret = true ;
        }
        return ret ;
    }
}

