package org.maachang.proxy.engine.mobile ;

import org.maachang.proxy.engine.mobile.carrier.MobileData;
import org.maachang.proxy.engine.mobile.emoji.ConvertEmoji;
import org.maachang.proxy.engine.mobile.emoji.EmojiConfig;
import org.maachang.proxy.engine.mobile.image.ConvertImage;
import org.maachang.proxy.engine.net.RequestInfo;
import org.maachang.proxy.engine.net.ResponseInfo;
import org.maachang.util.AnalysisUtil;
import org.maachang.util.CharsetMask;
import org.maachang.util.GZIPBinary;
import org.maachang.util.StringUtil;
import org.maachang.util.ZenToHan;

/**
 * レスポンス情報を携帯専用変換.
 *
 * @version 2008/04/08
 * @author  masahito suzuki
 * @since   MaachangProxy 1.01
 */
public class ConvertMobile {
    
    /**
     * レスポンス情報を携帯専用変換します.
     * @param res 対象のレスポンス情報を設定します.
     * @param info 対象のモバイルアクセスデータを設定します.
     * @exception Exception 例外.
     */
    public static final void convert( ResponseInfo res,MobileInfo info )
        throws Exception {
        RequestInfo req = info.getRequest() ;
        EmojiConfig conf = info.getEmojiConfig() ;
        MobileData data = info.getMobileData() ;
        boolean gzip = false ;
        // 携帯からのアクセス.
        if( data != null ) {
            // 圧縮されている場合は、解凍.
            if( res.getHeader( "Content-Encoding",0 ) != null ) {
                String c = res.getHeader( "Content-Encoding",0 ) ;
                if( c.indexOf( "zip" ) > 0 ) {
                    byte[] body = GZIPBinary.getInstance().convertGZIPByBinary( res.getBody() ) ;
                    res.setBody( body ) ;
                    res.removeHeader( "Content-Encoding" ) ;
                    gzip = true ;
                }
            }
            byte[] body = res.getBody() ;
            // レスポンスが、HTML系の場合は、SHIFT_JISに変換.
            String type = res.getHeader( "Content-Type",0 ) ;
            if( type != null && ( type.indexOf( "text/html" ) >= 0 ||
                type.indexOf( "application/xhtml" ) >= 0 ||
                type.indexOf( "text/xml" ) >= 0 ) ) {
                String charset = getCharset( type ) ;
                String mobCharset ;
                boolean isShiftJisFlag = false ;
                if( "softbank".equals( data.getCarrier() ) ) {
                    mobCharset = conf.getCharset( conf.getCarrierName( data ) ) ;
                    if( CharsetMask.WIN31J.equals( mobCharset ) ) {
                        mobCharset = "SHIFT_JIS" ;
                    }
                }
                else {
                    // DoCoMo,auの場合.
                    mobCharset = "SHIFT_JIS" ;
                    isShiftJisFlag = true ;
                }
                if( charset != null ) {
                    boolean srcNoChangeCharsetFlag = false ;
                    String tmp = null ;
                    // キャラクタセットが同じ場合.
                    if( mobCharset.toLowerCase().equals( charset.trim().toLowerCase() ) ) {
                        tmp = new String( body,mobCharset ) ;
                        srcNoChangeCharsetFlag = true ;
                    }
                    // Body内容のCharsetをキャリアのキャラクタセットに変換.
                    else {
                        tmp = new String( body,charset ) ;
                        tmp = StringUtil.changeString( tmp,"charset="+charset,"charset="+mobCharset ) ;
                    }
                    if( isShiftJisFlag == true ) {
                        tmp = AnalysisUtil.toSJIS( tmp ) ;
                    }
                    tmp = ZenToHan.convertHankaku( tmp ) ;
                    body = tmp.getBytes( mobCharset ) ;
                    res.setBody( body ) ;
                    tmp = null ;
                    // キャリアの条件によって、charsetが変換された場合.
                    if( srcNoChangeCharsetFlag == false ) {
                        // Content-Lengthのcharsetは、SHIFT_JISとする.
                        int x = type.toLowerCase().indexOf( "charset" ) ;
                        if( x <= -1 ) {
                            x = type.indexOf( ";" ) ;
                            if( x > 0 ) {
                                type = type.substring( 0,x ) ;
                            }
                            type = new StringBuilder().append( type ).
                                append( "; charset=" ).append( mobCharset ).toString() ;
                        }
                        else {
                            int xx = type.indexOf( ";" ) ;
                            if( xx > 0 ) {
                                type = type.substring( 0,xx ) ;
                            }
                            else {
                                type = type.substring( 0,x ) ;
                            }
                            type = new StringBuilder().append( type ).
                                append( "; charset=" ).append( mobCharset ).toString() ;
                        }
                        res.putHeader( "Content-Type",type ) ;
                    }
                }
            }
        }
        // PCでアクセスされ、GZIP圧縮されている.
        else if( res.getHeader( "Content-Encoding",0 ) != null ) {
            String c = res.getHeader( "Content-Encoding",0 ) ;
            if( c.indexOf( "zip" ) > 0 ) {
                gzip = true ;
                res.setBody( GZIPBinary.getInstance().convertGZIPByBinary( res.getBody() ) ) ;
            }
        }
        // 絵文字変換.
        if( ConvertEmoji.convert( res,conf,data ) == false ) {
            // 画像変換.
            ConvertImage.convert( req,res,data ) ;
        }
        // PCで圧縮されていた場合.
        if( data == null && gzip == true ) {
            // 再圧縮.
            res.setBody( GZIPBinary.getInstance().convertBinaryByGZIP( res.getBody() ) ) ;
        }
        // レスポンスBody長を設定.
        res.putHeader( "Content-Length",String.valueOf( res.getBody().length ) ) ;
    }
    
    /** キャラクタセットを取得. */
    private static final String getCharset( String type ) {
        if( type != null ) {
            int p = type.indexOf( "charset=" ) ;
            if( p > 0 ) {
                return CharsetMask.getCharset( type.substring( p+"charset=".length() ) ) ;
            }
        }
        return null ;
    }
}


