package org.maachang.proxy.engine;

import java.net.InetAddress;

import org.maachang.proxy.engine.conf.AccessManager;
import org.maachang.proxy.engine.conf.RefusalAddressManager;
import org.maachang.proxy.engine.conf.SerializableObject;
import org.maachang.proxy.engine.conf.ServerOption;
import org.maachang.proxy.engine.conf.SslOption;
import org.maachang.proxy.engine.net.http.NetService;
import org.maachang.proxy.engine.net.server.ProxyManager;
import org.maachang.util.conf.Config;

/**
 * Proxyエンジンサービス.
 * 
 * @version 2008/03/25
 * @author masahito suzuki
 * @since MaachangProxy 1.00
 */
public class EngineService {
    private NetService netService = null ;
    private ProxyManager proxyManager = null ;
    private RefusalAddressManager refusal = null ;
    private AccessManager accessManager = null ;
    
    /**
     * コンストラクタ.
     */
    public EngineService() {
        
    }
    
    /**
     * コンストラクタ.
     * @param serverConf サーバコンフィグを設定します.
     * @param sslConf SSLコンフィグを設定します.
     * @exception Exception 例外.
     */
    public EngineService( Config serverConf,Config sslConf )
        throws Exception {
        open( serverConf,sslConf ) ;
    }
    
    /**
     * デストラクタ.
     */
    protected void finalize() throws Exception {
        this.close() ;
    }
    
    /**
     * オープン処理.
     * @param serverConf サーバコンフィグを設定します.
     * @param sslConf SSLコンフィグを設定します.
     * @exception Exception 例外.
     */
    public void open( Config serverConf,Config sslConf )
        throws Exception {
        try {
            if( serverConf == null || sslConf == null ) {
                throw new IllegalArgumentException( "引数は不正です" ) ;
            }
            ServerOption serverOpt = ServerOption.create( serverConf ) ;
            SslOption sslOpt = SslOption.create( serverConf ) ;
            this.proxyManager = SerializableObject.getInstance().decodeSerializeByProxy() ;
            this.refusal = SerializableObject.getInstance().decodeSerializeByRefusalAddress() ;
            this.accessManager = SerializableObject.getInstance().decodeSerializeByAccess() ;
            this.netService = new NetService() ;
            if( serverOpt.getBindAddress() == null ) {
                this.netService.open( new ProxyReceiveCallback( this.proxyManager,this.refusal,this.accessManager ),
                    sslOpt,serverOpt.getConnectLength(),serverOpt.getPoolLength(),
                    serverOpt.getPort() ) ;
            }
            else {
                this.netService.open( new ProxyReceiveCallback( this.proxyManager,this.refusal,this.accessManager ),
                    sslOpt,serverOpt.getConnectLength(),serverOpt.getPoolLength(),
                    InetAddress.getByName( serverOpt.getBindAddress() ),
                    serverOpt.getPort() ) ;
            }
        } catch( Exception e ) {
            this.close() ;
            throw e ;
        }
    }
    
    /**
     * クローズ処理.
     */
    public void close() {
        //if( proxyManager != null ) {
        //    try {
        //        SerializableObject.getInstance().encodeSerializableByProxy( proxyManager ) ;
        //    } catch( Exception e ) {
        //    }
        //}
        //if( refusal != null ) {
        //    try {
        //        SerializableObject.getInstance().encodeSerializableByRefusalAddress( refusal ) ;
        //    } catch( Exception e ) {
        //    }
        //}
        if( accessManager != null ) {
            try {
                SerializableObject.getInstance().encodeSerializableByAccess( accessManager ) ;
            } catch( Exception e ) {
            }
        }
        if( netService != null ) {
            netService.close() ;
        }
        netService = null ;
        proxyManager = null ;
    }
    
    /**
     * オブジェクトが有効かチェック.
     * @return boolean [true]の場合、有効です.
     */
    public boolean isUse() {
        return proxyManager.isUse() ;
    }
}
