package org.maachang.rimdb.search ;

import org.maachang.rimdb.Row;
import org.maachang.rimdb.SearchResult;
import org.maachang.rimdb.table.RowImpl;
import org.maachang.rimdb.table.TableImpl;

/**
 * 検索結果情報.
 * 
 * @version 2014/07/14
 * @author  masahito suzuki
 * @since   rimdb-1.00
 */
public final class SearchResultImpl implements SearchResult {
    
    /** テーブル情報. **/
    private final TableImpl table ;
    
    /** 行情報. **/
    private final RowImpl row ;
    
    /**
     * 検索行.
     * int[0]の場合は、検索行サイズに従う.
     */
    private final int[] lines ;
    
    /**
     * 検索行サイズ.
     * -1の場合は、全部.
     * 0の場合は、ゼロ件.
     */
    private final int length ;
    
    /** 検索カーソル. **/
    private int cursor ;
    
    /** オフセット値. **/
    private int offset ;
    
    /** リミット値. **/
    private int limit ;
    
    /**
     * コンストラクタ.
     * @param table 対象のテーブルを設定します.
     * @param lines 対象の行情報を設定します.
     * @param lenght 対象の行数を設定します.
     */
    protected SearchResultImpl( TableImpl table,int[] lines,int length ) {
        this.table = table ;
        this.row = table.getRow() ;
        this.lines = lines ;
        this.length = length ;
        this.cursor = 0 ;
        
        // 初期のオフセット、リミット値をセット.
        this.offset = 0 ;
        this.limit = getMax() ;
    }
    
    /**
     * オフセット値、リミット値の初期値をセット.
     * @param offset 対象のオフセット値を設定します.
     * @param limit 対象のリミット値を設定します.
     * @return SearchResultImpl オブジェクトが返却されます.
     */
    protected final SearchResultImpl setDefine( int offset,int limit ) {
        
        int max = getMax() ;
        if( offset < 0 ) {
            offset = 0 ;
        }
        if( limit < 0 ) {
            limit = max - offset ;
        }
        
        if( offset >= max ) {
            offset = max ;
            limit = 0 ;
        }
        else if( limit >= max - offset ) {
            limit = max - offset ;
        }
        
        this.offset = offset ;
        this.limit = limit ;
        if( cursor < offset ) {
            cursor = offset ;
        }
        return this ;
    }
    
    /**
     * 情報クリア.
     */
    public final void clear() {
        row.clear() ;
        this.cursor = offset ;
    }
    
    /**
     * テーブル名を取得.
     * @return String テーブル名が返却されます.
     */
    public final String getName() {
        return table.getName() ;
    }
    
    /**
     * テーブルオブジェクトを取得.
     * @return Table テーブルオブジェクトが返却されます.
     */
    public final TableImpl getTable() {
        return table ;
    }
    
    /**
     * 現在カーソル位置の行情報を取得.
     * @return Row 現在カーソル位置の行情報が返却されます.
     */
    public final Row get() {
        if( length == 0 ) {
            return null ;
        }
        else if( length < 0 ) {
            return row.position( cursor ) ;
        }
        else {
            return row.position( lines[ cursor ] ) ;
        }
    }
    
    /**
     * 先頭行に移動.
     * @return SearchResult オブジェクトが返却されます.
     */
    public final SearchResultImpl first() {
        if( length != 0 ) {
            cursor = offset ;
        }
        return this ;
    }
    
    /**
     * 最終行に移動.
     * @return SearchResult オブジェクトが返却されます.
     */
    public final SearchResultImpl last() {
        if( length != 0 ) {
            cursor = offset + limit ;
        }
        return this ;
    }
    
    /**
     * 指定行に移動.
     * @param no 移動先の行を指定します.
     * @return SearchResult オブジェクトが返却されます.
     */
    public final SearchResultImpl setRow( final int no ) {
        if( length != 0 ) {
            if( no <= offset ) {
                cursor = offset ;
            }
            else if( no >= offset + limit ) {
                cursor = offset + limit ;
            }
            else {
                cursor = no ;
            }
        }
        return this ;
    }
    
    /**
     * 現在の行番号を取得.
     * @return int 現在の行番号が返却されます.
     */
    public final int getRow() {
        return cursor ;
    }
    
    /**
     * 件数を取得.
     * @return int 件数が返却されます.
     */
    public final int getLength() {
        return limit ;
    }
    
    /**
     * 最大件数を取得.
     * ※offset,limitが定義されていない場合は[getLength()]と同様の値が返却されます.
     * @return int 最大件数が返却されます.
     */
    public final int getMax() {
        if( length <= 0 ) {
            if( length == 0 ) {
                return 0 ;
            }
            return table.length() ;
        }
        return length ;
    }
    
    /**
     * 次の件数の情報が存在するかチェック.
     * @return boolean [true]の場合、存在します.
     */
    public final boolean hasNext() {
        if( length == 0 ) {
            return false ;
        }
        if( cursor >= offset + limit ) {
            return false ;
        }
        return true ;
    }
    
    /**
     * 現在のカーソル情報を取得.
     * @return Row 現在のカーソル情報を取得.
     */
    public final Row next() {
        if( length == 0 || cursor >= offset + limit ) {
            return null ;
        }
        if( length < 0 ) {
            return row.position( cursor ++ ) ;
        }
        else {
            return row.position( lines[ cursor ++ ] ) ;
        }
    }
    
    /**
     * 現在位置の情報を削除.
     */
    public final void remove() {
        throw new UnsupportedOperationException() ;
    }
    
}
