package org.fda.evaluator;



import org.fda.alignment.ScaffoldContig;
import org.fda.alignment.Alignment;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.fda.intervaltree.IntervalSearchTree;
import org.fda.intervaltree.Interval;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//import org.fda.data.Enums.QUALITYLEVEL;
import org.fda.data.Enums.CoverageType;
import org.fda.data.QUAL;

import org.fda.data.Reference;
import org.fda.data.ReferenceSet;
import org.fda.intervaltree.MergedIntervalSearchTree;

/**
 *
 * @author Gokhan.Yavas
 */
public class IntervalMerger {

    private final Map<Reference, IntervalSearchTree> mergedIntervalTreeMap;
    private final Map<Reference, Long> totalRealSizeOfAlignedContigsByChr;


    private long totCoveredLen = 0L;
    private long totalCoveredReferenceSizeSoFar=0;
    long totalGenomeLength = 0;    
    private double totalCovRatio;
    private long totAlignedLengthOnContigs=0L;
    //private QUALITYLEVEL quallevel;
    private QUAL quallevel;
    private double duplicationRatio;
    private double validityRatio;
    private long totContigLength=0L;

    private final EvaluatorBase ev;
    private final ReferenceSet refset;

    public double getDuplicationRatio() {
        return duplicationRatio;
    }
    public double getInvDupRatio(){
        if(duplicationRatio==0)
            return 0;
        else
            return 1/duplicationRatio;
    }

         
    
    public double getTotCovRatio(){
        return totalCovRatio;
    }
    
    //public IntervalMerger(ReferenceSet cset, QUALITYLEVEL qual, StandaloneEvaluatorLegacy ev) throws FileNotFoundException, IOException{
    //public IntervalMerger(ReferenceSet cset, QUALITYLEVEL qual, EvaluatorBase ev) throws FileNotFoundException, IOException{
    public IntervalMerger(ReferenceSet cset, QUAL qual, EvaluatorBase ev) throws FileNotFoundException, IOException{
        this.refset = cset;
        this.ev = ev;
        this.quallevel = qual;
                  
        mergedIntervalTreeMap = new HashMap<>(); 
        totalRealSizeOfAlignedContigsByChr = new HashMap<>();
        
        Map<CoverageType, Integer> tmp;
        for(Reference c : refset.getRefs()){
            mergedIntervalTreeMap.put(c, new MergedIntervalSearchTree());
            totalRealSizeOfAlignedContigsByChr.put(c, 0L);
            totalGenomeLength = totalGenomeLength+ c.getLength();
        }
    }
    public ReferenceSet getChrSet(){
        return this.refset;
    }
    
    public Map<Reference, IntervalSearchTree> getMergedIntervalTreeMap(){
        return mergedIntervalTreeMap;
    }
    public Map<Reference, List<Interval>> getIntervalListsFromChrTrees(Map<Reference, IntervalSearchTree> treeMap){
        Map<Reference, List<Interval>> map = new HashMap<>();        
        IntervalSearchTree chrTree;
        List<Interval> intList;
        
        for(Reference c : refset.getRefs()){
            chrTree = treeMap.get(c);
            intList = chrTree.inOrder();
            map.put(c, intList);
        }
        return map;        
    }
    public void process(ScaffoldContig ent, boolean generateSubs) throws IOException{      
        
        IntervalSearchTree chrTree;

        for(Alignment a : ent.getAlignments()){
            
            chrTree = mergedIntervalTreeMap.get(a.getReference());
            totalCoveredReferenceSizeSoFar-=((MergedIntervalSearchTree)chrTree).getTotalSize();
            ((MergedIntervalSearchTree)chrTree).put(a.getReferenceInterval(), generateSubs);
            // Add the updated size of the intervals for that reference
            totalCoveredReferenceSizeSoFar+=((MergedIntervalSearchTree)chrTree).getTotalSize();
            totalRealSizeOfAlignedContigsByChr.put(a.getReference(), totalRealSizeOfAlignedContigsByChr.get(a.getReference())+a.getRefAlignmentLength());            
            totAlignedLengthOnContigs += a.getContigAlignmentLength();
        }        
        totContigLength+=ent.getContigLength();
    }    
    public void finalize_process(long totContSizeWOgaps){    
        
        totalCovRatio = Math.min(1,(double)totalCoveredReferenceSizeSoFar / (refset.getGenomesize()-refset.getGapsize()));
        //totalCovPercentage = (double)totalCoveredReferenceSizeSoFar / (refset.getGenomesize()-refset.getGapsize());
        
        //this.totalCovRatio = (double)totalCoveredReferenceSizeSoFar / (double)this.totalGenomeLength;
        if(totalCoveredReferenceSizeSoFar!=0)
            duplicationRatio = Math.max(1, (double) totAlignedLengthOnContigs / (double) totalCoveredReferenceSizeSoFar);
        else
            duplicationRatio =0;
        if(totContigLength!=0){            
            validityRatio = Math.min((double)totAlignedLengthOnContigs/totContSizeWOgaps, 1);            
        }
        else
            validityRatio=0;
    }

    public double getValidityRatio() {
        return validityRatio;
    }

    //public QUALITYLEVEL getQuallevel() {
    public QUAL getQuallevel() {
        return quallevel;
    }

    //public void setQuallevel(QUALITYLEVEL quallevel) {
    public void setQuallevel(QUAL quallevel) {
        this.quallevel = quallevel;
    }
    
}
