package org.maachang.proxy.engine.mobile.carrier ;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

import org.maachang.util.FileUtil;
import org.maachang.util.conf.Config;
import org.maachang.util.conf.ReadIni;

/**
 * carrierコンフィグ.
 *
 * @version 2008/04/08
 * @author  masahito suzuki
 * @since   MaachangProxy 1.01
 */
public class CarrierConfig {
    
    /**
     * コンフィグファイル.
     */
    private static final String CARRIER_CONF = "./conf/carrier/carrier.conf" ;
    
    /**
     * コンフィグ基本セクション名.
     */
    private static final String SECTION = "carrier" ;
    
    /**
     * キャリア判別用セクション名.
     */
    private static final String AGENT_SECTION = "carrier-agent" ;
    
    /**
     * 再読み込み間隔.
     */
    private static final long RELOAD_TIME = 5000L ;
    
    /**
     * キャリアコンフィグ.
     */
    private Config conf = null ;
    
    /**
     * サポートキャリアに対する詳細オブジェクト管理.
     */
    private HashMap<String,MobileConfig> manager = null ;
    
    /**
     * ファイル日付.
     */
    private long lastTime = -1L ;
    
    /**
     * 前回アクセスタイム.
     */
    private long beforeTime = -1L ;
    
    /**
     * コンストラクタ.
     */
    public CarrierConfig() {
        beforeTime = -1 ;
    }
    
    /**
     * 対象コンフィグファイルを読み込む.
     */
    private void read() {
        if( beforeTime + RELOAD_TIME <= System.currentTimeMillis() ) {
            try {
                boolean flg = false ;
                if( conf == null ) {
                    flg = true ;
                }
                else {
                    long t = FileUtil.getLastTime( CARRIER_CONF ) ;
                    if( t != lastTime ) {
                        lastTime = t ;
                        flg = true ;
                    }
                }
                if( flg == true ) {
                    BufferedReader br = new BufferedReader( new InputStreamReader(
                        new FileInputStream( CARRIER_CONF ),"UTF8" ) ) ;
                    try {
                        conf = new Config() ;
                        ReadIni.analisys( conf,br ) ;
                        br.close() ;
                        br = null ;
                    } finally {
                        if( br != null ) {
                            try {
                                br.close() ;
                            } catch( Exception e ) {
                            }
                        }
                    }
                    if( lastTime <= -1L ) {
                        lastTime = FileUtil.getLastTime( CARRIER_CONF ) ;
                    }
                    readSupportCarrier( conf ) ;
                    beforeTime = System.currentTimeMillis() ;
                }
            } catch( Exception e ) {
                conf = null ;
                manager = null ;
                lastTime = -1L ;
                beforeTime = -1L ;
            }
        }
    }
    
    /**
     * サポートキャリアを読み込む.
     */
    private void readSupportCarrier( Config conf )
        throws Exception {
        String[] names = conf.getAll( SECTION,"support" ) ;
        if( names != null && names.length > 0 ) {
            int len = names.length ;
            manager = new HashMap<String,MobileConfig>() ;
            for( int i = 0 ; i < len ; i ++ ) {
                MobileConfig mob = new MobileConfig( names[ i ] ) ;
                manager.put( names[ i ],mob ) ;
            }
        }
    }
    
    /**
     * バージョンを取得.
     * @return String バージョンが返されます.
     */
    public synchronized String getVersion() {
        read() ;
        if( conf == null ) {
            return null ;
        }
        return conf.get( SECTION,"version",0 ) ;
    }
    
    /**
     * バージョン日付を取得.
     * @return String バージョン日付が返されます.
     */
    public synchronized String getVersionDate() {
        read() ;
        if( conf == null ) {
            return null ;
        }
        return conf.get( SECTION,"update",0 ) ;
    }
    
    /**
     * サポートキャリア名一覧を取得.
     * @return String[] サポートキャリア一覧が返されます.
     */
    public synchronized String[] getSupportCarrier() {
        read() ;
        if( conf == null ) {
            return null ;
        }
        return conf.getAll( SECTION,"support" ) ;
    }
    
    /**
     * １つの機種データを取得.
     * @param carrier 対象のキャリア名を設定します.
     * @return MobileConfig 対象の機種コンフィグ情報が返されます.
     */
    public synchronized MobileConfig getMobileConfig( String carrier ) {
        read() ;
        if( conf == null ) {
            return null ;
        }
        return manager.get( carrier ) ;
    }
    
    /**
     * 指定ユーザエージェントがどのキャリアに一致するかチェック.
     * @param userAgent 対象のユーザエージェントを設定します.
     * @return MobileData 対象の機種情報が返されます.<BR>
     *                [null]の場合は、PCです.
     */
    public synchronized MobileData getAgent( String userAgent ) {
        if( userAgent == null || ( userAgent = userAgent.trim() ).length() <= 0 ) {
            return null ;
        }
        read() ;
        if( conf == null ) {
            return null ;
        }
        String[] keys = conf.getKeys( AGENT_SECTION ) ;
        if( keys != null && keys.length > 0 ) {
            int len = keys.length ;
            for( int i = 0 ; i < len ; i ++ ) {
                if( userAgent.indexOf( keys[ i ] ) >= 0 ) {
                    String carrier = conf.get( AGENT_SECTION,keys[ i ],0 ) ;
                    MobileConfig mob = manager.get( carrier ) ;
                    if( mob == null ) {
                        return null ;
                    }
                    return mob.getMobileData( carrier,userAgent ) ;
                }
            }
        }
        return null ;
    }
}
