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

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;

import org.maachang.util.Digest;
import org.maachang.util.FileUtil;
import org.maachang.util.StringUtil;

/**
 * ke-tai.orgから取得したCSV情報をMaachangProxy用携帯コンフィグに変換.
 *
 * @version 2008/04/08
 * @author  masahito suzuki
 * @since   MaachangProxy 1.01
 */
public class ConvertKeTaiOrgList {
    
    /**
     * 出力先ディレクトリ名.
     */
    private static final String OUTPUT_DIR = "conf/carrier/" ;
    
    /**
     * シリアル格納位置.
     */
    private static final String SERIAL = "/Serial" ;
    
    /**
     * CSV開始Y.
     */
    private static final int START_Y = 3 ;
    
    /**
     * CSV-X長.
     */
    private static final int LENGTH_X = 25 ;
    
    /**
     * CSV取得X-1.
     * 
     * メーカ名,
     * 機種名.
     * UserAgent.
     * 機種タイプ.
     * ブラウザX.
     * ブラウザY.
     */
    private static final int[] START_X = {
        1,3,4,5,7,8 } ;
    
    /**
     * CSV取得X-2.
     *
     * GIF.
     * JPEG.
     * PNG.
     * Flash.
     */
    private static final int[] START_X2 = {
        11,12,13,14 } ;
    
    /**
     * コンストラクタ.
     */
    public ConvertKeTaiOrgList() {
        
    }
    
    /**
     * メイン.
     */
    public static final void main( String[] args ) throws Exception {
        if( args == null || args.length <= 0 ) {
            return ;
        }
        InputStream stream = null ;
        try {
            String file = FileUtil.getFullPath( args[ 1 ] ) ;
            stream = new FileInputStream( file ) ;
            String outDir = args[ 0 ] ;
            if( outDir.endsWith( "/" ) == false && outDir.endsWith( "\\" ) == false ) {
                outDir += "/" ;
            }
            outDir += OUTPUT_DIR ;
            String simulator = getSimulator( args ) ;
            new ConvertKeTaiOrgList().execution( stream,outDir,simulator ) ;
        } catch( Exception e ) {
            throw e ;
        } finally {
            if( stream != null ) {
                try {
                    stream.close() ;
                } catch( Exception ee ) {
                }
            }
            stream = null ;
        }
    }
    
    /**
     * 処理実行.
     * @param stream 対象のInputStreamを設定します.
     * @param outDir 出力先のディレクトリ名を設定します.
     * @param simulator シミュレータ用出力条件を設定します.
     */
    public void execution( InputStream stream,String outDir,String simulator ) throws Exception {
        BufferedReader reader = new BufferedReader( new InputStreamReader( stream,"Windows-31J" ) ) ;
        ByteArrayOutputStream docomo = new ByteArrayOutputStream() ;
        ByteArrayOutputStream au = new ByteArrayOutputStream() ;
        ByteArrayOutputStream softbank = new ByteArrayOutputStream() ;
        
        PrintWriter b1 = new PrintWriter( new OutputStreamWriter( docomo,"UTF8" ) ) ;
        b1.print( "[" ) ;b1.print( "docomo" ) ;b1.println( "]" ) ;
        PrintWriter b2 = new PrintWriter( new OutputStreamWriter( au,"UTF8" ) ) ;
        b2.print( "[" ) ;b2.print( "au" ) ;b2.println( "]" ) ;
        PrintWriter b3 = new PrintWriter( new OutputStreamWriter( softbank,"UTF8" ) ) ;
        b3.print( "[" ) ;b3.print( "softbank" ) ;b3.println( "]" ) ;
        
        // それぞれの内容をメモリに展開.
        for( int i = 0 ;; i ++ ) {
            String one = reader.readLine() ;
            if( one == null ) {
                break ;
            }
            if( i < START_Y ) {
                continue ;
            }
            ArrayList<String> lst = StringUtil.cutString( one,"," ) ;
            if( lst == null || lst.size() < LENGTH_X ) {
                continue ;
            }
            cutCote( lst ) ;
            // 機種判別.
            String ki = lst.get( START_X[0] ) ;
            if( ki == null || ( ki = ki.trim() ).length() <= 0 ) {
                continue ;
            }
            PrintWriter p = null ;
            ki = ki.toLowerCase() ;
            int mobileType = 0 ;
            // 機種条件がDocomo.
            if( "docomo".equals( ki ) ) {
                p = b1 ;
                mobileType = 1 ;
            }
            // 機種条件がAU.
            else if( "au".equals( ki ) ) {
                p = b2 ;
                mobileType = 2 ;
            }
            // 機種条件がSoftBank.
            else if( "softbank".equals( ki ) || "vodafone".equals( ki ) ) {
                p = b3 ;
                mobileType = 3 ;
            }
            // それ以外の場合は処理しない.
            else {
                continue ;
            }
            
            // ユーザーエージェントを取得.
            String agent = lst.get( START_X[2] ) ;
            String code = lst.get( START_X[1] ) ;
            String type = lst.get( START_X[3] ) ;
            String x = lst.get( START_X[4] ) ;
            String y = lst.get( START_X[5] ) ;
            if( agent == null || ( agent = agent.trim() ).length() <= 0 ||
                ( agent = StringUtil.changeString( agent,"　"," " ).trim() ).length() <= 0 ||
                code == null || ( code = code.trim() ).length() <= 0 ||
                x == null || ( x = x.trim() ).length() <= 0 ||
                y == null || ( y = y.trim() ).length() <= 0 ) {
                continue ;
            }
            if( agent.indexOf( SERIAL ) != -1 ) {
                agent = agent.substring( 0,agent.indexOf( SERIAL ) ) ;
                if( agent.lastIndexOf( "[" ) != -1 ) {
                    agent = agent.substring( 0,agent.lastIndexOf( "[" ) ) ;
                }
            }
            boolean gif = false ;
            boolean jpg = false ;
            boolean png = false ;
            boolean flash = false ;
            String tmp = null ;
            tmp = lst.get( START_X2[0] ) ;
            if( tmp != null && ( tmp = tmp.trim() ).length() > 0 && "1".equals( tmp ) ) {
                gif = true ;
            }
            tmp = lst.get( START_X2[1] ) ;
            if( tmp != null && ( tmp = tmp.trim() ).length() > 0 && "1".equals( tmp ) ) {
                jpg = true ;
            }
            tmp = lst.get( START_X2[2] ) ;
            if( tmp != null && ( tmp = tmp.trim() ).length() > 0 && "1".equals( tmp ) ) {
                png = true ;
            }
            tmp = lst.get( START_X2[3] ) ;
            if( tmp != null && ( tmp = tmp.trim() ).length() > 0 && "1".equals( tmp ) ) {
                flash = true ;
            }
            if( gif == false && jpg == false && png == false ) {
                jpg = true ;
            }
            agent = agent.trim() ;
            p.print( "agent=" ) ;p.print( "\"" ) ;p.print( agent ) ;p.println( "\"" ) ;
            // 機種情報.
            p.print( "code=" ) ;p.print( "\"" ) ;p.print( code ) ;p.println( "\"" ) ;
            // 機種タイプ.
            p.print( code ) ;p.print( ".type=" ) ;p.print( "\"" ) ;p.print( type ) ;p.println( "\"" ) ;
            // ブラウザX.
            p.print( code ) ;p.print( ".x=\"" ) ;p.print( x ) ;p.println( "\"" ) ;
            // ブラウザy.
            p.print( code ) ;p.print( ".y=\"" ) ;p.print( y ) ;p.println( "\"" ) ;
            // jpeg.
            p.print( code ) ;p.print( ".jpg=\"" ) ;p.print( jpg ) ;p.println( "\"" ) ;
            // gif.
            p.print( code ) ;p.print( ".gif=\"" ) ;p.print( gif ) ;p.println( "\"" ) ;
            // png.
            p.print( code ) ;p.print( ".png=\"" ) ;p.print( png ) ;p.println( "\"" ) ;
            // flash.
            p.print( code ) ;p.print( ".flash=\"" ) ;p.print( flash ) ;p.println( "\"" ) ;
            // softbankで、シミュレータがONの場合.
            if( mobileType == 3 && "on".equals( simulator ) ) {
                int pp = agent.indexOf( "/" ) ;
                if( pp <= -1 ) {
                    continue ;
                }
                if( agent.startsWith( "SoftBank/" ) ) {
                    agent = new StringBuilder().append( "Semulator" ).append( agent.substring( pp ) ).toString() ;
                }
                else if( agent.startsWith( "Vodafone/" ) ) {
                    agent = new StringBuilder().append( "Vemulator" ).append( agent.substring( pp ) ).toString() ;
                }
                else {
                    agent = new StringBuilder().append( "J-EMULATOR" ).append( agent.substring( pp ) ).toString() ;
                }
                code = "SIM@" + code ;
                p.print( "agent=" ) ;p.print( "\"" ) ;p.print( agent ) ;p.println( "\"" ) ;
                // 機種情報.
                p.print( "code=" ) ;p.print( "\"" ) ;p.print( code ) ;p.println( "\"" ) ;
                // 機種タイプ.
                p.print( code ) ;p.print( ".type=" ) ;p.print( "\"" ) ;p.print( type ) ;p.println( "\"" ) ;
                // ブラウザX.
                p.print( code ) ;p.print( ".x=\"" ) ;p.print( x ) ;p.println( "\"" ) ;
                // ブラウザy.
                p.print( code ) ;p.print( ".y=\"" ) ;p.print( y ) ;p.println( "\"" ) ;
                // jpeg.
                p.print( code ) ;p.print( ".jpg=\"" ) ;p.print( jpg ) ;p.println( "\"" ) ;
                // gif.
                p.print( code ) ;p.print( ".gif=\"" ) ;p.print( gif ) ;p.println( "\"" ) ;
                // png.
                p.print( code ) ;p.print( ".png=\"" ) ;p.print( png ) ;p.println( "\"" ) ;
                // flash.
                p.print( code ) ;p.print( ".flash=\"" ) ;p.print( flash ) ;p.println( "\"" ) ;
            }
        }
        // IMode用シミュレータを出力.
        if( "on".equals( simulator ) ) {
        	PrintWriter p = b1 ;
            String code = "ISIM2.0" ;
            p.print( "agent=" ) ;p.print( "\"" ) ;p.print( "DoCoMo/2.0 ISIM" ) ;p.println( "\"" ) ;
            // 機種情報.
            p.print( "code=" ) ;p.print( "\"" ) ;p.print( code ) ;p.println( "\"" ) ;
            // 機種タイプ.
            p.print( code ) ;p.print( ".type=" ) ;p.print( "\"" ) ;p.print( "ISIM" ) ;p.println( "\"" ) ;
            // ブラウザX.
            p.print( code ) ;p.print( ".x=\"" ) ;p.print( "240" ) ;p.println( "\"" ) ;
            // ブラウザy.
            p.print( code ) ;p.print( ".y=\"" ) ;p.print( "270" ) ;p.println( "\"" ) ;
            // jpeg.
            p.print( code ) ;p.print( ".jpg=\"" ) ;p.print( "true" ) ;p.println( "\"" ) ;
            // gif.
            p.print( code ) ;p.print( ".gif=\"" ) ;p.print( "true" ) ;p.println( "\"" ) ;
            // png.
            p.print( code ) ;p.print( ".png=\"" ) ;p.print( "false" ) ;p.println( "\"" ) ;
            // flash.
            p.print( code ) ;p.print( ".flash=\"" ) ;p.print( "true" ) ;p.println( "\"" ) ;
        }
        b1.flush() ;
        b2.flush() ;
        b3.flush() ;
        
        String sha1 = null ;
        sha1 = Digest.convert( "SHA1",docomo.toByteArray() ) ;
        b1.println( "sha1=\""+sha1+"\"" ) ;
        sha1 = Digest.convert( "SHA1",au.toByteArray() ) ;
        b2.println( "sha1=\""+sha1+"\"" ) ;
        sha1 = Digest.convert( "SHA1",softbank.toByteArray() ) ;
        b3.println( "sha1=\""+sha1+"\"" ) ;
        
        b1.flush() ;
        b2.flush() ;
        b3.flush() ;
        
        // 集計結果をファイルに出力.
        FileUtil.setFile( outDir+"docomo.conf",docomo.toByteArray() ) ;
        FileUtil.setFile( outDir+"au.conf",au.toByteArray() ) ;
        FileUtil.setFile( outDir+"softbank.conf",softbank.toByteArray() ) ;
        b1.close() ;
        b2.close() ;
        b3.close() ;
        docomo.close() ;
        au.close() ;
        softbank.close() ;
    }
    
    /**
     * 前後のコーテーションを外す.
     */
    private void cutCote( ArrayList<String> lst ) {
        int len = lst.size() ;
        for( int i = 0 ; i < len ; i ++ ) {
            String one = lst.get( i ) ;
            if( one == null || ( one = one.trim() ).length() <= 0 ) {
                lst.set( i,"" ) ;
            }
            one = StringUtil.catCote( one ) ;
            if( one == null || ( one = one.trim() ).length() <= 0 ) {
                lst.set( i,"" ) ;
            }
            else {
                lst.set( i,one ) ;
            }
        }
    }
    
    /**
     * シミュレータ用出力.
     */
    private static final String getSimulator( String[] args ) {
        if( args.length >= 3 ) {
            return args[ 2 ] ;
        }
        return null ;
    }
}
