package org.maachang.comet.httpd.engine.script.dao;

import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import org.maachang.dao.MaachangDaoException;
import org.maachang.dao.dbms.DbUtil;
import org.maachang.dao.dbms.MetaColumn;
import org.maachang.util.Base64;


/**
 * DaoUtil.
 * 
 * @version 2007/11/04
 * @author masahito suzuki
 * @since MaachangComet 1.00
 */
public class DaoUtil {
    
    /**
     * 指定日付を文字列変換.
     * <BR><BR>
     * 指定日付を文字列に変換します.
     * <BR>
     * @param date 対象の日付情報を設定します.
     * @return String 対象の文字列が返されます.
     * @exception Exception 例外.
     */
    public static final String convertDateByString( java.util.Date date )
        throws Exception {
        SimpleDateFormat fmt = new SimpleDateFormat( "yyyy,M,d,H,m,s" ) ;
        return fmt.format( date ) ;
    }
    
    /**
     * javascript日付情報を、java.util.Dateに変換.
     * <BR><BR>
     * javascript日付情報を、java.util.Dateに変換します.
     * <BR>
     * @param string 対象の日付情報を設定します.
     * @return java.util.Date 日付オブジェクトが返されます.
     * @exception Exception 例外.
     */
    public static final java.util.Date convertStringByDate( String string )
        throws Exception {
        SimpleDateFormat fmt = new SimpleDateFormat( "EEE MMM dd yyyy HH:mm:ss 'GMT'Z' (JST)'",Locale.US ) ;
        return fmt.parse( string ) ;
    }
    
    /**
     * 指定データをDB形式に合わせて変換.
     * <BR><BR>
     * 指定データをDB形式に合わせて変換します.
     * <BR>
     * @param meta 対象のメタカラム情報を設定します.
     * @param model 対象のモデル名を設定します.
     * @param name 対象のカラム名を設定します.
     * @param value 変換対象の要素を設定します.
     * @return Object 変換されたオブジェクトが返されます.
     * @exception MaachangDaoException MaachangDao例外.
     */
    public static Object convertByDBObject( MetaColumn meta,String model,String name,Object value )
        throws MaachangDaoException {
        int type = -1; 
        try {
            if( value == null ) {
                return null ;
            }
            int no = meta.getColumnNameByNumber( DbUtil.convertJavaNameByDBName( name ) ) ;
            if( no == -1 ) {
                throw new MaachangDaoException( "指定モデル[" + model +
                    "]に、カラム名[" + name + "]は存在しません" ) ;
            }
            type = meta.getColumnType( no ) ;
            switch( type ) {
                case Types.BOOLEAN :// Boolean.
                case Types.BIT :
                case Types.TINYINT :
                case Types.CHAR :
                    if( value instanceof String ) {
                        value = new Boolean( ( String )value ) ;
                    }
                    else if( ( value instanceof Boolean ) == false ) {
                        value = null ;
                    }
                    break ;
                case Types.SMALLINT :// Integer.
                case Types.INTEGER :
                    if( value instanceof String ) {
                        value = new Integer( convertFloatByInteger( ( String )value ) ) ;
                    }
                    else {
                        value = new Integer( convertFloatByInteger( String.valueOf( value ) ) ) ;
                    }
                    break ;
                case Types.BIGINT :// Long.
                    if( value instanceof String ) {
                        value = new Long( ( String )value ) ;
                    }
                    else {
                        value = new Long( convertFloatByInteger( String.valueOf( value ) ) ) ;
                    }
                    break ;
                case Types.DOUBLE :// Double.
                    if( value instanceof String ) {
                        value = new Double( ( String )value ) ;
                    }
                    else {
                        value = new Double( String.valueOf( value ) ) ;
                    }
                    break ;
                case Types.FLOAT :// Float.
                case Types.REAL :// Float.
                    if( value instanceof String ) {
                        value = new Float( ( String )value ) ;
                    }
                    else {
                        value = new Float( String.valueOf( value ) ) ;
                    }
                    break ;
                case Types.VARCHAR :// String.
                case Types.LONGVARCHAR :
                case Types.DATALINK :// URL.
                    if( ( value instanceof String ) == false ) {
                        value = String.valueOf( value ) ;
                    }
                    break ;
                case Types.DATE :// java.sql.Date.
                case Types.TIME :// java.sql.Time.
                case Types.TIMESTAMP :// java.sql.Timestamp.
                    if( value instanceof java.util.Date ) {
                        long time = ( ( java.util.Date )value ).getTime() ;
                        if( type == Types.DATE ) {
                            value = new java.sql.Date( time ) ;
                        }
                        else if( type == Types.TIME ) {
                            value = new java.sql.Time( time ) ;
                        }
                        else if( type == Types.TIMESTAMP ) {
                            value = new java.sql.Timestamp( time ) ;
                        }
                    }
                    else if( ( type == Types.DATE && value instanceof java.sql.Date ) == false &&
                        ( type == Types.TIME && value instanceof java.sql.Time ) == false &&
                        ( type == Types.TIMESTAMP && value instanceof java.sql.Timestamp ) == false ) {
                        value = null ;
                    }
                    break ;
                case Types.BINARY :// byte[].
                case Types.VARBINARY :
                case Types.LONGVARBINARY :
                case Types.BLOB :
                    if( value instanceof String ) {
                        value = Base64.decode( ( String )value ) ;
                    }
                    else if( ( value instanceof byte[] ) == false ) {
                        value = null ;
                    }
                    break ;
                default :
                    value = null ;
                    break ;
            }
            // データ型が一致しない場合.
            if( value == null ) {
                throw new MaachangDaoException( "テーブル[" + model +
                    "]に対するカラム[" + name + "]の型は不正です" ) ;
            }
            //System.out.println( " model:" + model + " column:" + name + " type:" + type + " object:" + value.getClass().getName() ) ;
            return value ;
        } catch( MaachangDaoException md ) {
            throw md ;
        } catch( Exception e ) {
            throw new MaachangDaoException( e ) ;
        }
    }
    
    /**
     * １つの戻り結果情報を変換.
     * <BR><BR>
     * １つの戻り結果情報を変換します.
     * <BR>
     * @param model 対象のモデル名を設定します.
     * @param name 対象のカラム名を設定します.
     * @param data 変換対象の情報を設定します.
     * @return Object 変換された内容が返されます.
     * @exception MaachangDaoException MaachangDao例外.
     */
    public static final Object convertResult( String model,String name,Object data )
        throws MaachangDaoException {
        // データ型が一致しない場合.
        if( data == null ) {
            return null ;
        }
        // 日付関連.
        else if( data instanceof java.sql.Date ||
            data instanceof java.sql.Time ||
            data instanceof java.sql.Timestamp ) {
            Calendar cal = Calendar.getInstance() ;
            cal.setTime( ( java.util.Date )data ) ;
            if( data instanceof java.sql.Date ) {
                StringBuilder buf = new StringBuilder() ;
                buf.append( "new Date:" ) ;
                buf.append( cal.get(Calendar.YEAR) ) ;
                buf.append( "," ) ;
                buf.append( (cal.get(Calendar.MONTH)+1) ) ;
                buf.append( "," ) ;
                buf.append( cal.get(Calendar.DAY_OF_MONTH) ) ;
                buf.append( ",0,0,0" ) ;
                return buf.toString() ;
            }
            else if( data instanceof java.sql.Time ) {
                StringBuilder buf = new StringBuilder() ;
                buf.append( "new Date:0,1,0," ) ;
                buf.append( cal.get(Calendar.HOUR_OF_DAY) ) ;
                buf.append( "," ) ;
                buf.append( cal.get(Calendar.MINUTE) ) ;
                buf.append( "," ) ;
                buf.append( cal.get(Calendar.SECOND) ) ;
                return buf.toString() ;
            }
            else if( data instanceof java.sql.Timestamp ) {
                StringBuilder buf = new StringBuilder() ;
                buf.append( "new Date:" ) ;
                buf.append( cal.get(Calendar.YEAR) ) ;
                buf.append( "," ) ;
                buf.append( (cal.get(Calendar.MONTH)+1) ) ;
                buf.append( "," ) ;
                buf.append( cal.get(Calendar.DAY_OF_MONTH) ) ;
                buf.append( "," ) ;
                buf.append( cal.get(Calendar.HOUR_OF_DAY) ) ;
                buf.append( "," ) ;
                buf.append( cal.get(Calendar.MINUTE) ) ;
                buf.append( "," ) ;
                buf.append( cal.get(Calendar.SECOND) ) ;
                return buf.toString() ;
            }
        }
        // バイナリ関連.
        else if( data instanceof byte[] ) {
            return data ;
        }
        // プリミティブ系.
        else if( data instanceof Boolean ||
            data instanceof Integer ||
            data instanceof Long ||
            data instanceof Float ||
            data instanceof Double ||
            data instanceof String ) {
            return data ;
        }
        throw new MaachangDaoException( "指定モデル[" + model +
            "]のカラム名[" + name + "]型は不正[" +
            data.getClass().getName() + "]です." ) ;
    }
    
    /**
     * 小数点が存在する場合は、削除.
     */
    private static final String convertFloatByInteger( String value ) {
        int p = value.indexOf( "." ) ;
        if( p != -1 ) {
            return value.substring( 0,p ) ;
        }
        return value ;
    }
    
    
}
