package org.maachang.rimdb.index ;

import org.maachang.rimdb.RimDbException;
import org.maachang.rimdb.util.NAdd;
import org.maachang.rimdb.util.OList;


/**
 * In検索ポインター.
 * 
 * @version 2014/06/29
 * @author  masahito suzuki
 * @since   rimdb-1.00
 */
@SuppressWarnings("unchecked")
public abstract class InPointer<W> extends SearchPointer<Index<W>> {
    
    /** 一致行. **/
    protected int[] position ;
    
    /** 検索ワード. **/
    protected OList<W> word ;
    
    /**
     * 情報リセット.
     * @param mode [true]を設定した場合、設定ワード条件も削除します.
     */
    public void reset( boolean mode ) {
        super.reset( mode ) ;
        if( mode ) {
            word = null ;
        }
        position = null ;
    }
    
    /**
     * 情報セット.
     * @param word 対象の情報を設定します.
     */
    public void set( OList<W> word ) {
        if( word == null ) {
            throw new RimDbException( "[" + this.getClass().getName() + "]検索条件にnullは設定できません" ) ;
        }
        this.word = word ;
        this.resetFlag = false ;
    }
    
    /**
     * インデックス位置群を取得.
     * @return int[] インデックス位置群が返却されます.
     */
    public final int[] position() {
        return position ;
    }
    
    /**
     * 検索処理.
     * @param index 対象のインデックスを設定します.
     */
    public final void search( final Index<W> index ) {
        
        if( resetFlag ) {
            throw new RimDbException( "[" + this.getClass().getName() + "]条件が設定されていません" ) ;
        }
        
        int p,len,cnt ;
        len = 0 ;
        cnt = 0 ;
        final int iLen = word.size() ;
        final MaskLine[] lm = index.getMaskLine() ;
        position = new int[ iLen ] ;
        for( int i = 0 ; i < iLen ; i ++ ) {
            if( ( p = index.eq( word.get( i ) ) ) == -1 ) {
                position[ i ] = -1 ;
            }
            else {
                position[ i ] = p ;
                cnt += lm[ p ].length ;
                len ++ ;
            }
        }
        length = len ;
        count = cnt ;
    }
    
    /**
     * 検索結果情報をNAdd情報に格納.
     * ※この処理は、検索条件が１件の場合に利用します.
     * @param out 検索結果の行情報をNAdd情報にセットします.
     * @param index 対象のインデックスを設定します.
     */
    public final void get( final NAdd out,final Index<W> index ) {
        
        int j,lenJ ;
        int[] n ;
        
        final int[][] indexToLine = ((Index)index).getIndexToLine() ;
        final int[] pos = position ;
        final int len = pos.length ;
        
        for( int i = 0 ; i < len ; i ++ ) {
            if( pos[ i ] == -1 ) {
                continue ;
            }
            n = indexToLine[ pos[ i ] ] ;
            lenJ = n.length ;
            for( j = 0 ; j < lenJ ; j ++ ) {
                out.add( n[ j ] ) ;
            }
        }
    }
    
    /** ベースコピー. **/
    protected void baseCopy( final boolean mode,final InPointer o ) {
        super.baseCopy( mode,o ) ;
        if( !mode ) {
            o.word = word ;
            o.resetFlag = false ;
        }
        o.position = null ;
    }
    
}
