package org.maachang.comet;

import java.util.ArrayList;

import org.maachang.util.FileUtil;
import org.maachang.util.Os;

/**
 * MaachangCometプロジェクト生成用.
 * 
 * @version 2007/09/20
 * @author masahito suzuki
 * @since MaachangComet 1.00
 */
public class Project {
    
    /**
     * 生成ディレクトリ一覧.
     */
    private static final String[] CREATE_DIR = {
        MaachangDef.DIRECTORY_CONFIG,
        MaachangDef.DIRECTORY_APPLICATION,
        MaachangDef.DIRECTORY_MODEL,
        MaachangDef.DIRECTORY_LIB,
        MaachangDef.DIRECTORY_JAR,
        MaachangDef.DIRECTORY_LOG,
        MaachangDef.DIRECTORY_TABLE,
        MaachangDef.DIRECTORY_ERROR_PAGE,
        MaachangDef.DIRECTORY_TEMPLATE,
        MaachangDef.DIRECTORY_PUBLIC,
        MaachangDef.DIRECTORY_PUBLIC+MaachangDef.DIRECTORY_IMAGE,
        MaachangDef.DIRECTORY_PUBLIC+MaachangDef.DIRECTORY_CSS,
        MaachangDef.DIRECTORY_PUBLIC+MaachangDef.DIRECTORY_JS,
        MaachangDef.DIRECTORY_PUBLIC+MaachangDef.UPLOAD_IMAGE_DIR,
        MaachangDef.DIRECTORY_STARTUP,
        MaachangDef.DIRECTORY_CRON,
        MaachangDef.DIRECTORY_TAGLIB,
        MaachangDef.DIRECTORY_REPORT
    } ;
    
    /**
     * コピーディレクトリ一覧.
     */
    private static final String[] COPY_DIR = {
        MaachangDef.DIRECTORY_CONFIG,
        MaachangDef.DIRECTORY_APPLICATION,
        MaachangDef.DIRECTORY_STARTUP,
        MaachangDef.DIRECTORY_PUBLIC
    } ;
    
    /**
     * Windowsサービス用ディレクトリ.
     */
    private static final String WINSERVICE_DIR = ".wsrv" ;
    private static final String SRC_WSRV = "sh/startup/windows/" ;
    
    /**
     * コンストラクタ.
     */
    private Project() {
        
    }
    
    /**
     * メインメソッド.
     * <BR><BR>
     * @param args Javaからのパラメータが設定されます.
     * @exception Exception 例外.
     */
    public static final void main( String[] args )
        throws Exception {
        new Project().execution( args ) ;
    }
    
    /**
     * 実行処理.
     */
    private void execution( String[] args )
        throws Exception {
        if( args == null || args.length <= 0 ) {
            throw new IllegalArgumentException( "MaachangCometディレクトリが必要です" ) ;
        }
        // OSが、Windows系かチェック.
        boolean isWindowsOs = Os.getInstance().isOs( Os.OS_WINNT ) ;
        
        int projType = -1 ;
        if( args.length >= 2 ) {
            if( "derby".equals( args[ 1 ].trim().toLowerCase() ) ) {
                projType = 1 ;
            }
            else if( "postgre".equals( args[ 1 ].trim().toLowerCase() ) ) {
                projType = 2 ;
            }
            else if( "mysql".equals( args[ 1 ].trim().toLowerCase() ) ) {
                projType = 3 ;
            }
            else if( "help".equals( args[ 1 ].trim().toLowerCase() ) ||
                "?".equals( args[ 1 ].trim().toLowerCase() ) ) {
                System.out.println( " mproj [database]" ) ;
                System.out.println( " [database] プロジェクトに対するデータベースを設定します." ) ;
                System.out.println( "            MaachangCometでは、以下のデータベースをサポートします." ) ;
                System.out.println( "            derby   : Apache Derby(JavaDB)用プロジェクトを作成します." ) ;
                System.out.println( "            postgre : Postgre用プロジェクトを作成します." ) ;
                System.out.println( "            mysql   : MySQL用プロジェクトを作成します." ) ;
                System.out.println() ;
                System.out.println( " またパラメータなしの場合、データベースに依存しない、プロジェクト雛型を" ) ;
                System.out.println( " 作成します." ) ;
                return ;
            }
        }
        
        System.out.println( "*** maachang comet - プロジェクト生成 - ***" ) ;
        System.out.println() ;
        
        String dir = FileUtil.getFullPath( "." ) ;
        if( dir.endsWith( "\\" ) || dir.endsWith( "/" ) ) {
            dir = dir.substring( 0,dir.length()-1 ) ;
        }
        dir += FileUtil.FILE_SPACE ;
        String baseDir = FileUtil.getFullPath( args[ 0 ] ) ;
        if( baseDir.endsWith( "\\" ) || baseDir.endsWith( "/" ) ) {
            baseDir = baseDir.substring( 0,baseDir.length()-1 ) ;
        }
        baseDir += FileUtil.FILE_SPACE ;
        
        // 指定カレントディレクトリ以下にディレクトリを生成.
        int len = CREATE_DIR.length ;
        for( int i = 0 ; i < len ; i ++ ) {
            System.out.print( "...[" ) ;
            FileUtil.mkdirs( dir+CREATE_DIR[ i ] ) ;
            System.out.println( CREATE_DIR[ i ] + "] を生成" ) ;
        }
        // OSがWindowsの場合、Windowsサービス用ディレクトリを生成.
        if( isWindowsOs ) {
            System.out.print( "...[" ) ;
            FileUtil.mkdirs( dir+WINSERVICE_DIR ) ;
            System.out.println( WINSERVICE_DIR + "] を生成" ) ;
        }
        
        System.out.println() ;
        
        // 指定カレントディレクトリ以下にディレクトリ以下をコピー.
        len = COPY_DIR.length ;
        for( int i = 0 ; i < len ; i ++ ) {
            System.out.println( "..." + COPY_DIR[ i ] + " 内容をコピー" ) ;
            copyDirBySrcToDest( baseDir+COPY_DIR[ i ],COPY_DIR[ i ] ) ;
        }
        
        // OSがWindowsの場合、Windowsサービス用ディレクトリにサービス情報をコピー.
        if( isWindowsOs ) {
            System.out.println( "** windowsサービス内容をコピー" ) ;
            copyDirBySrcToDest( baseDir+SRC_WSRV,WINSERVICE_DIR ) ;
        }
        
        System.out.println() ;
        
        // 指定されたJDBCドライバをコピー.
        String jdbcName = null ;
        // derby用コピー.
        if( projType == 1 ) {
            jdbcName = "derby" ;
        }
        // postgre用コピー.
        else if( projType == 2 ) {
            jdbcName = "postgre" ;
        }
        // mysql用コピー.
        else if( projType == 3 ) {
            jdbcName = "mysql" ;
        }
        // DBプロジェクト名が設定されている場合.
        if( jdbcName != null ) {
            System.out.println() ;
            System.out.println() ;
            System.out.println( "## JDBC:"+jdbcName+"用コピー" ) ;
            copyDirBySrcToDest( baseDir+"database/"+jdbcName+"/lib/","./jar/" ) ;
            copyFile( baseDir+"/database"+jdbcName+"/conf/record.conf","./conf/record.conf" ) ;
        }
        
        System.out.println() ;
        
        // OSにあわせて起動コマンドをコピー.
        if( Os.getInstance().getOS() == Os.OS_WINNT ) {
            // windows系の内容をコピー.
            copyFile( baseDir+"sh/mscript.cmd","mscript.cmd" ) ;
            copyFile( baseDir+"sh/mserver.cmd","mserver.cmd" ) ;
        }
        else {
            // Linux系の内容をコピー.
            copyFile( baseDir+"sh/mscript","mscript" ) ;
            copyFile( baseDir+"sh/mserver","mserver" ) ;
        }
    }
    
    /**
     * srcディレクトリ内のファイルを、destディレクトリにコピー.
     */
    private final void copyDirBySrcToDest( String src,String dest )
        throws Exception {
        src = FileUtil.getFullPath( src ) ;
        if( src.endsWith( "\\" ) || src.endsWith( "/" ) ) {
            src = src.substring( 0,src.length() - 1 ) ;
        }
        dest = FileUtil.getFullPath( dest ) ;
        if( dest.endsWith( "\\" ) || dest.endsWith( "/" ) ) {
            dest = dest.substring( 0,dest.length() - 1 ) ;
        }
        ArrayList<String> lst = FileUtil.getListAll( src ) ;
        if( lst != null ) {
            int len = lst.size() ;
            for( int i = 0 ; i < len ; i ++ ) {
                String s = lst.get( i ) ;
                if( s == null ) {
                    continue ;
                }
                copyFile( src+s,dest+s ) ;
            }
        }
    }
    
    /**
     * ファイル内容をコピー.
     */
    private final boolean copyFile( String src,String dest )
        throws Exception {
        if( FileUtil.isFileExists( src ) ) {
            String destDir = getDir( dest ) ;
            if( destDir != null && FileUtil.isDirExists( destDir ) == false ) {
                FileUtil.mkdirs( destDir ) ;
            }
            byte[] bin = FileUtil.getFile( src ) ;
            if( bin != null ) {
                 FileUtil.setFile( dest,bin ) ;
                 return true ;
            }
        }
        return false ;
    }
    
    /**
     * 指定フルパス内のディレクトリ名を取得.
     */
    private final String getDir( String file )
        throws Exception {
        int p = file.lastIndexOf( "\\" ) ;
        if( p == -1 ) {
            p = file.lastIndexOf( "/" ) ;
            if( p == -1 ) {
                return null ;
            }
        }
        return file.substring( 0,p ) ;
    }
    
}
