package org.maachang.comet.conf ;

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

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

/**
 * javascript内でデフォルトインポートされるパッケージ名管理.
 *
 * @version 2007/08/29
 * @author  masahito suzuki
 * @since   MaachangComet 1.00
 */
public class PackagesConfig {
    
    /**
     * ターゲットセクション名.
     */
    private static final String BASE_SECTION = "import-package" ;
    
    /**
     * キャラクタセット.
     */
    private static final String CHARSET = "UTF8" ;
    
    /**
     * 読み込みファイル名.
     */
    private static final String READ_FILE = MaachangDef.DIRECTORY_CONFIG+"packages.conf" ;
    
    /**
     * 読み込み対象データ.
     */
    private Config iniParams = null ;
    
    /**
     * 対象ファイル.
     */
    private String fileName = null ;
    
    /**
     * 管理パッケージ名群.
     */
    private String[] packages = null ;
    
    /**
     * 最終更新日.
     */
    private long lastUpdate = -1L ;
    
    /**
     * 更新ID.
     */
    private int updateId = 0 ;
    
    /**
     * オープン.
     * <BR><BR>
     * オープンします.
     * <BR>
     * @exception Exception 例外.
     */
    public synchronized void open() throws Exception {
        this.open( READ_FILE ) ;
    }
    
    /**
     * オープン.
     * <BR><BR>
     * オープンします.
     * <BR>
     * @param name 対象のファイル名を設定します.
     * @exception Exception 例外.
     */
    public synchronized void open( String name ) throws Exception {
        this.fileName = FileUtil.getFullPath( name ) ;
        try {
            this.reload() ;
        } catch( Exception e ) {
           this.close() ;
           throw e ;
        } finally {
        }
    }
    
    /**
     * クローズ.
     * <BR><BR>
     * クローズ処理.
     */
    public synchronized void close() {
        iniParams = null ;
        fileName = null ;
        lastUpdate = -1L ;
        packages = null ;
        updateId = 0 ;
    }
    
    /**
     * パッケージ名群を取得.
     * <BR><BR>
     * 格納されているパッケージ名群を取得します.
     * <BR>
     * @return String[] パッケージ名群が返されます.
     * @exception Exception 例外.
     */
    public synchronized String[] getPackages()
        throws Exception {
        updateByReload() ;
        if( packages != null ) {
            return packages ;
        }
        String[] ret = iniParams.getAll( BASE_SECTION,"package" ) ;
        if( ret != null && ret.length > 0 ) {
            int len = ret.length ;
            for( int i = 0 ; i < len ; i ++ ) {
                if( ret[i] == null || ( ret[i] = ret[i].trim() ).length() <= 0 ) {
                    ret[i] = null ;
                    continue ;
                }
                //if( ret[i].startsWith( "Packages." ) == false ) {
                //    ret[i] = "Packages." + ret[i] ;
                //}
                if( ret[i].startsWith( "var " ) == false ) {
                    ret[i] = "var " +ret[i]+ " = Packages." + ret[i] + ";" ;
                }
            }
        }
        packages = ret ;
        return ret ;
    }
    
    /**
     * 更新IDを取得.
     * <BR><BR>
     * 更新IDを取得します.
     * <BR>
     * @return int 更新IDが返されます.
     */
    public synchronized int getUpdateId() {
        updateByReload() ;
        return updateId ;
    }
    
    /**
     * 再読み込み.
     */
    private final void reload()
        throws Exception {
        BufferedReader buf = null ;
        if( FileUtil.isFileExists( fileName ) == true ) {
            try {
                buf = new BufferedReader(
                    new InputStreamReader(
                        new FileInputStream( fileName ),CHARSET ) ) ;
                Config iniParams = new Config() ;
                ReadIni.analisys( iniParams,buf ) ;
                buf.close() ;
                buf = null ;
                long last = FileUtil.getLastTime( fileName ) ;
                // 読み込みデータを設定.
                this.iniParams = iniParams ;
                this.lastUpdate = last ;
            } catch( Exception e ) {
                throw e ;
            } finally {
                if( buf != null ) {
                    try {
                        buf.close() ;
                    } catch( Exception e ) {
                    }
                }
            }
        }
    }
    
    /**
     * ファイルが更新されている場合は、再読み込み.
     */
    private void updateByReload() {
        try {
            long tm = FileUtil.getLastTime( fileName ) ;
            if( lastUpdate != tm ) {
                this.reload() ;
                packages = null ;
                updateId ++ ;
                if( updateId >= 10000 ) {
                    updateId = 0 ;
                }
            }
        } catch( Exception e ) {
        }
    }
}
