
package org.fda.alignment;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import org.fda.basicstats.BasicStatsComputeFromList;
import org.fda.data.Utilities;

/**
 *
 * @author Gokhan.Yavas
 */
public class AlignmentFilterQ extends AlignmentFilter{

    public AlignmentFilterQ(BlockingQueue queue, int no, BlockingQueue oqueue) {
        super(queue, oqueue);
        id = "ContigFilter"+no;
    }
    public AlignmentFilterQ(BlockingQueue queue, int no, BlockingQueue oqueue, BasicStatsComputeFromList bsc) {
        super(queue, oqueue, bsc);
        id = "ContigFilter"+no;
    }
    
    private List<Alignment> filterU(ScaffoldContig as){
        int i, j, n;
        int olap, leni, lenj;
        long score, diff;
        AlignmentWrapper[] lis = createAlignmentWrappers(as.getAlignments()).toArray(new AlignmentWrapper[0]);

        n = lis.length;
          //-- Continue until all equivalent repeats are extracted
        List<Integer> allbest = new ArrayList<>();
        do{          
        //-- Dynamic
            for ( i = 0; i < n; ++ i ){
                if(lis[i].getUsed()) 
                    continue;
                leni = lis[i].getAlign().getContigAlignmentLength();
                lis[i].setScore(Utilities.scoreLocal (0, leni, 0, 0, lis[i].getAlign().getIdentity(), 0));
                lis[i].setFrom(-1);
                lis[i].setDiff( 0);
            
                for ( j = 0; j < i; ++ j ){
                    if ( lis[j].getUsed() )
                        continue;
                    if ( lis[j].getFrom() >= 0 && lis[lis[j].getFrom()].getAlign().getContEnd() >= lis[i].getAlign().getContSt() )
                        continue;
                    lenj = lis[j].getAlign().getContigAlignmentLength();
                    olap = lis[j].getAlign().overlapContig(lis[i].getAlign());
                    if ( olap < 0 )
                        olap = 0;
                    diff = lis[j].getDiff() + diffAligns (lis[i].getAlign(), lis[j].getAlign());
                    score = Utilities.scoreLocal(lis[j].getScore(), leni, lenj, olap, lis[i].getAlign().getIdentity(), Utilities.maxOverlap);
//                    if ( score > lis[i].getScore() || (score == lis[i].getScore() && diff < lis[i].getDiff()) ){

                    if ( score > lis[i].getScore() || (score == lis[i].getScore() && diff < lis[i].getDiff()) ||  
//                            (score == lis[i].getScore() && diff == lis[i].getDiff() && lis[j].getAlign().getReference().getRefID().equalsIgnoreCase(as.getId()))){
                            (score == lis[i].getScore() && diff == lis[i].getDiff() && Arrays.equals(lis[j].getAlign().getReference().getSeqHashValue(), as.getSeqHashValue()))){
//                        if((score == lis[i].getScore() && diff == lis[i].getDiff() && lis[j].getAlign().getReference().getRefID().equalsIgnoreCase(as.getId()))){
//                            //System.out.println((score == lis[i].getScore() && diff == lis[i].getDiff() && Arrays.equals(lis[j].getAlign().getReference().getSeqHashValue(), as.getSeqHashValue())));
//                            for(byte b : as.getSeqHashValue())
//                                System.out.print(b);
//                            System.out.println();
//                            for(byte b : lis[j].getAlign().getReference().getSeqHashValue())
//                                System.out.print(b);
//                            System.out.println(Utilities.ls);
//
//                        }
                            
                        lis[i].setFrom(j);
                        lis[i].setScore(score);
                        lis[i].setDiff(diff);
                    }
                }
            }
        } while ( updateBest (lis, n, allbest, Utilities.epsilon) );
        //int beg = pickBest (lis, allbest, Utilities.epsilon);
        int beg = 0;
        int end = allbest.size();
        if ( beg == end ) beg = 0;
        else end = beg + 1;
        List<Alignment> a2ret = new ArrayList();
        for ( ; beg < end; ++ beg )
            for( i = allbest.get(beg); i >= 0  &&  i < n; i = lis[i].getFrom() ){
                a2ret.add(lis[i].getAlign());              
            }
        return a2ret;
    
    }
    @Override
    public void filter(ScaffoldContig as){
        List<Alignment> a2ret = filterU(as);
        setAlignments(as, a2ret);
    }        
    
}
