package org.maachang.mimdb.core ;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.maachang.mimdb.core.impl.EqualsNoList;

/**
 * Remote用結果行要素.
 * 
 * @version 2014/01/20
 * @author masahito suzuki
 * @since MasterInMemDB 1.02
 */
@SuppressWarnings("unchecked")
final class RemoteResultRow extends MimdbResultRow {
    
    /** 親オブジェクト. **/
    protected RemoteResultImpl parent ;
    
    /** カウント情報. **/
    protected boolean countFlag ;
    
    /**
     * コンストラクタ.
     */
    public RemoteResultRow() {}
    
    /**
     * コンストラクタ.
     * @param parent 親オブジェクトを設定します.
     */
    public RemoteResultRow( RemoteResultImpl parent ) {
        create( parent ) ;
    }
    
    /** ファイナライズ. **/
    protected void finalize() throws Exception {
        clear() ;
    }
    
    /**
     * 情報生成.
     * @param parent 親オブジェクトを設定します.
     */
    public void create( RemoteResultImpl parent ) {
        this.parent = parent ;
        this.countFlag = parent.compile.countFlag ;
    }
    
    /**
     * 情報クリア.
     */
    public void clear() {
        parent = null ;
    }
    
    /**
     * 更新IDを取得.
     * @return long 更新IDが返却されます.
     */
    public long getDbId() {
        return parent.compile.dbId ;
    }
    
    /**
     * テーブル名の取得.
     * @return String テーブル名が返却されます.
     */
    public String getName() {
        return parent.compile.name ;
    }
    
    /**
     * テーブル情報の取得.
     * @return BaseTable テーブル情報が返却されます.
     */
    public BaseTable getTable() {
        return parent.getTable() ;
    }
    
    /**
     * 対象の行番号を取得.
     * @return int 行番号が返却されます.
     */
    public int getLineNo() {
        return parent.nowRow ;
    }
    
    /** viewColumnListを取得. **/
    private final EqualsNoList viewColumnList() {
        return parent.meta.viewColumnList ;
    }
    
    /** 現在のsrcを取得. **/
    private final Object[] src() {
        return parent.values[ parent.nowRow - parent.position ] ;
    }
    
    /**
     * カラム項番で情報を取得.
     * @param n 対象の項番を設定します.
     * @return Object 情報が返却されます.
     */
    public Object getValue( int n ) {
        
        // カウント表示の場合.
        if( countFlag ) {
            if( n != 0 ) {
                return null ;
            }
            return src()[ n ] ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            n = viewColumnList.src( n ) ;
        }
        return src()[ n ] ;
    }
    
    /**
     * 指定カラム名に対する項番を取得.
     */
    private final int getColumnNameByNo( String name ) {
        
        // カウント表示の場合.
        if( countFlag ) {
            if( CountMetaDataImpl.COLUMN_NAME.equals( name ) ) {
                return -1 ;
            }
            return 0 ;
        }
        
        // 表示カラム条件が設定されている場合.
        BaseTable table = parent.getTable() ;
        EqualsNoList viewColumnList ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            int ret = table.getColumnNameByNo( name ) ;
            if( !viewColumnList.equals( ret ) ) {
                return -1 ;
            }
            return ret ;
        }
        return table.getColumnNameByNo( name ) ;
    }
    
    /*********************** 以下 Map定義 ***********************/
    
    public void putAll(Map toMerge) {
        // 処理なし.
    }
    public boolean containsValue(Object value) {
        
        // カウント表示の場合.
        if( countFlag ) {
            if( value instanceof Number ) {
                return ( (Number)value ).equals( src()[ 0 ] ) ;
            }
            return false ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            int[] vc = viewColumnList.arrays() ;
            int len = viewColumnList.size() ;
            Object[] values = src() ;
            if( value == null ) {
                for( int i = 0 ; i < len ; i ++ ) {
                    if( values[ vc[ i ] ] == null ) {
                        return true ;
                    }
                }
            }
            else {
                for( int i = 0 ; i < len ; i ++ ) {
                    if( value.equals( values[ vc[ i ] ] ) ) {
                        return true ;
                    }
                }
            }
        }
        else {
            BaseTable table = parent.getTable() ;
            int len = table.getColumnSize() ;
            Object[] values = src() ;
            if( value == null ) {
                for( int i = 0 ; i < len ; i ++ ) {
                    if( values[ i ] == null ) {
                        return true ;
                    }
                }
            }
            else {
                for( int i = 0 ; i < len ; i ++ ) {
                    if( value.equals( values[ i ] ) ) {
                        return true ;
                    }
                }
            }
        }
        return false ;
    }
    public Set entrySet() {
        // 処理なし.
        return null ;
    }
    public Collection values() {
        
        // カウント表示の場合.
        if( countFlag ) {
            List<Object> ret = new ArrayList<Object>() ;
            ret.add( src()[ 0 ] ) ;
            return ret ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            int[] vc = viewColumnList.arrays() ;
            int len = viewColumnList.size() ;
            List<Object> ret = new ArrayList<Object>( len ) ;
            Object[] values = src() ;
            for( int i = 0 ; i < len ; i ++ ) {
                ret.add( values[ vc[ i ] ] ) ;
            }
            return ret ;
        }
        else {
            BaseTable table = parent.getTable() ;
            int len = table.getColumnSize() ;
            List<Object> ret = new ArrayList<Object>( len ) ;
            Object[] values = src() ;
            for( int i = 0 ; i < len ; i ++ ) {
                ret.add( values[ i ] ) ;
            }
            return ret ;
        }
    }
    public Object put(Object name, Object value) {
        // 処理なし.
        return null ;
    }
    public boolean containsKey(Object key) {
        
        // カウント表示の場合.
        if( countFlag ) {
            if( key instanceof String ) {
                return CountMetaDataImpl.COLUMN_NAME.equals( key ) ;
            }
            else if( key instanceof Number ) {
                return ((Number)key).intValue() == 0 ;
            }
            return false ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        BaseTable table = parent.getTable() ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            if( key instanceof String ) {
                return getColumnNameByNo( (String)key ) != -1 ;
            }
            else if( key instanceof Number ) {
                int n = ((Number)key).intValue() ;
                return ( n >= 0 && n < viewColumnList.size() ) ;
            }
        }
        else {
            if( key instanceof String ) {
                return table.getColumnNameByNo( ((String)key).trim().toLowerCase() ) != -1 ;
            }
            else if( key instanceof Number ) {
                int n = ((Number)key).intValue() ;
                return ( n >= 0 && n < table.getColumnSize() ) ;
            }
        }
        return false ;
    }
    public Object get(Object key) {
        
        // カウント表示の場合.
        if( countFlag ) {
            if( key instanceof String ) {
                if( CountMetaDataImpl.COLUMN_NAME.equals( key ) ) {
                    return src()[ 0 ] ;
                }
            }
            else if( key instanceof Number ) {
                if( ((Number)key).intValue() == 0 ) {
                    return src()[ 0 ] ;
                }
            }
            return null ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            if( key instanceof String ) {
                int n = getColumnNameByNo( (String)key ) ;
                if( n != -1 ) {
                    return src()[ n ] ;
                }
                return null ;
            }
            else if( key instanceof Number ) {
                int n = ((Number)key).intValue() ;
                if( n >= 0 && n < viewColumnList.size() ) {
                    return src()[ viewColumnList.src( n ) ] ;
                }
                return null ;
            }
        }
        else {
            BaseTable table = parent.getTable() ;
            if( key instanceof String ) {
                int n = table.getColumnNameByNo( ((String)key).trim().toLowerCase() ) ;
                if( n == -1 ) {
                    return null ;
                }
                return src()[ n ] ;
            }
            else if( key instanceof Number ) {
                int n = ((Number)key).intValue() ;
                if( n >= 0 && n < table.getColumnSize() ) {
                    return src()[ n ] ;
                }
                return null ;
            }
        }
        return null ;
    }
    public Object remove(Object key) {
        // 処理なし.
        return null ;
    }
    public boolean isEmpty() {
        return false ;
    }
    public Set keySet() {
        Set<Object> ret = new HashSet<Object>() ;
        getAllKey( ret ) ;
        return ret ;
    }
    public int size() {
        
        // カウント表示の場合.
        if( countFlag ) {
            return 1 ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            return viewColumnList.size() ;
        }
        else {
            return parent.getTable().getColumnSize() ;
        }
    }
    public void getAllKey( Set<Object> set ) {
        
        // カウント表示の場合.
        if( countFlag ) {
            set.add( CountMetaDataImpl.COLUMN_NAME ) ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        BaseTable table = parent.getTable() ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            int[] vc = viewColumnList.arrays() ;
            int len = viewColumnList.size() ;
            String[] key = table.getColumns() ;
            for( int i = 0 ; i < len ; i ++ ) {
                set.add( key[ vc[ i ] ] ) ;
            }
        }
        else {
            int len = table.getColumnSize() ;
            String[] key = table.getColumns() ;
            for( int i = 0 ; i < len ; i ++ ) {
                set.add( key[ i ] ) ;
            }
        }
    }
    public void getAllValues( Set<Object> set ) {
        
        // カウント表示の場合.
        if( countFlag ) {
            set.add( src()[ 0 ] ) ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            int[] vc = viewColumnList.arrays() ;
            int len = viewColumnList.size() ;
            Object[] values = src() ;
            for( int i = 0 ; i < len ; i ++ ) {
                set.add( values[ vc[ i ] ] ) ;
            }
        }
        else {
            int len = parent.getTable().getColumnSize() ;
            Object[] values = src() ;
            for( int i = 0 ; i < len ; i ++ ) {
                set.add( values[ i ] ) ;
            }
        }
    }
    public String toString() {
        
        // カウント表示の場合.
        if( countFlag ) {
            return new StringBuilder( "{" ).append( CountMetaDataImpl.COLUMN_NAME ).
                append( ":" ).append( src()[ 0 ] ).append( "}" ).toString() ;
        }
        
        // 表示カラム条件が設定されている場合.
        EqualsNoList viewColumnList ;
        BaseTable table = parent.getTable() ;
        if( ( viewColumnList = viewColumnList() ) != null ) {
            int[] vc = viewColumnList.arrays() ;
            int len = viewColumnList.size() ;
            StringBuilder buf = new StringBuilder() ;
            String[] key = table.getColumns() ;
            Object[] values = src() ;
            buf.append( "{" ) ;
            for( int i = 0 ; i < len ; i ++ ) {
                if( i != 0 ) {
                    buf.append( "," ) ;
                }
                if( values[ vc[ i ] ] instanceof String ) {
                    buf.append( key[ vc[ i ] ] ).append( ":\"" ).append( values[ vc[ i ] ] ).append( "\"" ) ;
                }
                else {
                    buf.append( key[ vc[ i ] ] ).append( ":" ).append( values[ vc[ i ] ] ) ;
                }
            }
            return buf.append( "}" ).toString() ;
        }
        else {
            int len = table.getColumnSize() ;
            StringBuilder buf = new StringBuilder() ;
            String[] key = table.getColumns() ;
            Object[] values = src() ;
            buf.append( "{" ) ;
            for( int i = 0 ; i < len ; i ++ ) {
                if( i != 0 ) {
                    buf.append( "," ) ;
                }
                if( values[ i ] instanceof String ) {
                    buf.append( key[ i ] ).append( ":\"" ).append( values[ i ] ).append( "\"" ) ;
                }
                else {
                    buf.append( key[ i ] ).append( ":" ).append( values[ i ] ) ;
                }
            }
            return buf.append( "}" ).toString() ;
        }
    }
    
}
