package org.maachang.rimdb.index.number64 ;

import org.maachang.rimdb.RimDbException;
import org.maachang.rimdb.index.Index;
import org.maachang.rimdb.index.IndexUtil;
import org.maachang.rimdb.util.NAdd;

/**
 * Number64(long)インデックス.
 * 
 * @version 2014/07/02
 * @author  masahito suzuki
 * @since   rimdb-1.00
 */
public final class Number64Index extends Index<Long> {
    
    /** index情報. **/
    protected final long[] index ;
    
    /**
     * コンストラクタ.
     * @param index 対象のインデックスを設定します.
     * @param line 対象の行情報を設定します.
     * @param max 全体長を設定します.
     */
    public Number64Index( long[] index,int[][] line,int max ) {
        super( line,max ) ;
        this.index = index ;
    }
    
    /**
     * インデックス情報を取得.
     * @return int[] インデックス情報が返却されます.
     */
    public long[] getIndex() {
        return index ;
    }
    
    /**
     * 一致検索.
     * @param key 対象のキーを設定します.
     * @return int インデックス番号が返却されます.
     */
    public final int eq( final Long key ) {
        return IndexUtil.searchLong( index,key ) ;
    }
    
    /**
     * 大なり検索.
     * @param eq 一致を許可する場合には[true]をセットします.
     * @param key 対象のキーを設定します.
     * @return int インデックス番号が返却されます.
     */
    public final int big( final boolean eq,final Long key ) {
        if( index[ index.length-1 ] < key ) {
            return -1 ;
        }
        else if( eq ) {
            return IndexUtil.searchLongBS( true,index,key ) ;
        }
        else {
            int n = IndexUtil.searchLongBS( true,index,key ) ;
            if( index[ n ] == key && (++n) >= maxLine ) {
                return -1 ;
            }
            return n ;
        }
    }
    
    /**
     * 小なり検索.
     * @param eq 一致を許可する場合には[true]をセットします.
     * @param key 対象のキーを設定します.
     * @return int インデックス番号が返却されます.
     */
    public final int small( final boolean eq,final Long key ) {
        if( index[ 0 ] > key ) {
            return -1;
        }
        else if( eq ) {
            return IndexUtil.searchLongBS( false,index,key ) ;
        }
        else {
            int n = IndexUtil.searchLongBS( false,index,key ) ;
            if( index[ n ] == key && (--n) < 0 ) {
                return -1 ;
            }
            return n ;
        }
    }
    
    /**
     * between検索.
     * @param out 格納行情報を設定します.
     * @param start 開始値を設定します.
     * @param end 終了値を設定します.
     * @return boolean [true]の場合、範囲取得に成功しました.
     */
    public final boolean between( final int[] out,Long start,Long end ) {
        if( start > end ) {
            Long n = start ;
            start = end ;
            end = n ;
        }
        out[ 0 ] = IndexUtil.searchLongBS( true,index,start ) ;
        out[ 1 ] = IndexUtil.searchLongBS( false,index,end ) ;
        
        return ( index[ out[ 0 ] ] >= start || index[ out[ 1 ] ] >= end ) &&
            ( index[ out[ 0 ] ] <= start || index[ out[ 1 ] ] <= end ) ;
    }
    
    /**
     * 部分一致検索.
     * @param result 一致行情報を格納するListオブジェクトを設定します.
     * @param key 対象のLike条件を設定します.
     */
    public final void like( final NAdd result,String key ) {
        throw new RimDbException( "Number64ではLikeはサポートされていません" ) ;
    }
    
}

