package org.maachang.mimdb.core;

import org.maachang.mimdb.MimdbException;
import org.maachang.mimdb.core.util.AtomicNumber32;

/**
 * 検索結果情報.
 * 
 * @version 2013/10/11
 * @author masahito suzuki
 * @since MasterInMemDB 1.00
 */
class ResultImpl implements MimdbResult {
    long dbId ;
    
    MimdbTable table ;
    ResultCache cache ;
    MimdbMetaData meta ;
    MimdbResultRow row ;
    ResultPointer pointer ;
    
    int length ;
    int maxLength ;
    int cursor ;
    
    /** クリアフラグ **/
    protected final AtomicNumber32 clearFlag = new AtomicNumber32( 1 ) ;
    
    /**
     * コンストラクタ.
     */
    public ResultImpl() {
        
    }
    
    /** finalize. **/
    protected void finalize() throws Exception {
        clear() ;
    }
    
    /**
     * 情報生成.
     * @param id 対象のIDを設定します.
     * @param table 対象のテーブルオブジェクトを設定します.
     * @param meta 対象のメタ情報を設定します.
     * @@aram row 対象のRowオブジェクトを設定します.
     * @param pointer 対象のポインターオブジェクトを設定します.
     * @param length 対象のデータ長を設定します.
     * @param maxLength 対象の最大データ長を設定します.
     */
    public void create( long id,MimdbTable table,ResultCache cache,MimdbMetaData meta,
        MimdbResultRow row,ResultPointer pointer,int length,int maxLength ) {
        this.dbId = id ;
        this.table = table ;
        this.meta = meta ;
        this.row = row ;
        this.pointer = pointer ;
        this.length = length ;
        this.maxLength = maxLength ;
        this.cache = cache ;
        clearFlag.set( 0 ) ;
    }
    
    /**
     * 情報クリア.
     */
    public void clear() {
        long res = clearFlag.setToBeforeReturn( 1 ) ;
        if( res != 1 ) {
            cache.clear() ;
            dbId = -1L ;
            table = null ;
            meta = null ;
            row = null ;
            pointer = null ;
            length = 0 ;
            maxLength = 0 ;
            cursor = 0 ;
            ResultCache.put( cache ) ;
        }
    }
    
    /**
     * オブジェクトがクリアされたかチェック.
     * @return boolean [true]の場合、クリアされています.
     */
    public boolean isClear() {
        return clearFlag.get() == 1 ;
    }
    
    /** チェック. **/
    protected void check() {
        if( clearFlag.get() == 1 ) {
            throw new MimdbException( "オブジェクトがクリアーされています" ) ;
        }
    }
    
    /**
     * DB更新IDの取得.
     * @return long DB更新IDが返却されます.
     */
    public long getDbId() {
        check() ;
        return dbId ;
    }
    
    /**
     * メタデータを取得.
     * @return MimdbMetaData メタデータが返却されます.
     */
    public MimdbMetaData getMetaData() {
        check() ;
        return meta ;
    }
    
    /**
     * 最初の行に移動.
     * @return boolean [true]の場合、存在します.
     * @exception Exception 例外.
     */
    public boolean first() throws Exception {
        check() ;
        cursor = 0 ;
        return true ;
    }
    
    /**
     * 最後の行に移動.
     * @return boolean [true]の場合、存在します.
     * @exception Exception 例外.
     */
    public boolean last() throws Exception {
        check() ;
        cursor = length-1 ;
        return true ;
    }
    
    /**
     * 次の情報が存在するかチェック.
     * @return boolean [true]の場合、存在します.
     */
    public boolean next() {
        check() ;
        return ( cursor < length ) ;
    }
    
    /**
     * 指定行に移動.
     * @param no 対象の行番号を設定します.
     * @return boolean [true]の場合、存在します.
     * @exception Exception 例外.
     */
    public boolean absolute( int no ) throws Exception {
        check() ;
        if( no >= 0 && no < length ) {
            cursor = no ;
            return true ;
        }
        cursor = no ;
        return false ;
    }
    
    /**
     * 現在の行番号を取得.
     * @return int 現在の行番号が返却されます.
     */
    public int getRow() {
        check() ;
        return cursor ;
    }
    
    /**
     * フェッチサイズを設定.
     * ※この値は、サーバーモードでの接続のみ有効となります.
     * @param size フェッチサイズを設定します.
     * @return MimdbStatement このオブジェクトが返却されます.
     */
    public MimdbResult setFetchSize( int size ) {
        return this ;
    }
    
    /**
     * フェッチサイズを取得.
     * ※この値は、サーバーモードでの接続のみ有効となります.
     * @return int フェッチサイズが返却されます.
     */
    public int getFetchSize() {
        return -1 ;
    }
    
    /**
     * 結果データの取得.
     * @return MimdbResultRow 結果行情報が返却されます.
     * @exception Exception 例外.
     */
    public MimdbResultRow get() throws Exception {
        check() ;
        if( cursor < length ) {
            if( pointer != null ) {
                pointer.cursor = cursor ;
            }
            cursor ++ ;
            return row ;
        }
        throw new MimdbException( "終端に達しました" ) ;
    }
    
    /**
     * 結果データの取得.
     * @param no 対象の項番を設定します.
     * @return MimdbResultRow 結果行情報が返却されます.
     * @exception Exception 例外.
     */
    public MimdbResultRow get( int no ) throws Exception {
        check() ;
        if( no < 0 || no >= length ) {
            throw new MimdbException( "範囲外です" ) ;
        }
        cursor = no ;
        return get() ;
    }
    
    /**
     * 結果データ数を取得.
     * @return int 結果データ数が返却されます.
     */
    public int length() {
        check() ;
        return length ;
    }
    
    /**
     * 最大データ長を取得.
     * ※offset,limit値をセットした場合のみ有効.
     * @return int 最大データ長が返却されます.
     */
    public int maxLength() {
        check() ;
        return maxLength ;
    }
}

