package org.fda.basicstats;


import java.io.File;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.fda.data.Enums.LLevel;
import org.fda.data.Enums.NLevel;
import org.fda.data.Utilities;


/**
 *
 * @author Gokhan.Yavas
 */
public class BasicStatsComputeFromList {
    private final List<ContigRecord> contigLengths;
    
    private double mean = 0;
    private int median = 0;
    private int min = 0;
    private int max = 0;
    private final Map<NLevel, Integer> nlevels;
    private final Map<LLevel, Integer> llevels;
    private int contigNo=0;    
    private long totalcontigSize=0L;
    //private long[] cumulativeContigSize;
    //private final File basicStatsFile;
    private final File cumulativeContigSizeFile;
    private long total_gc_count=0L;
    private double total_gc_percent=0;   
    private final int level;
    private double maxPenaltyValue = 0;
    public long getTotalcontigSize() {
        return totalcontigSize;
    }

    public synchronized void setMaxPenaltyValue(double d){
        if(maxPenaltyValue < d)
            maxPenaltyValue = d;
    }
    public double getMaxPenaltyValue(){
        return maxPenaltyValue;
    }
    
    public BasicStatsComputeFromList(List<ContigRecord> contigLengths, int level){
        this.contigLengths =  contigLengths;
        nlevels = new TreeMap<>();
        llevels = new TreeMap<>();             
        
        this.level =level ;
        cumulativeContigSizeFile = new File(Utilities.rootDir.getAbsolutePath()+File.separator+"RESULTS"+File.separator+"L"+level+File.separator+"cumlength.bin");
        computeStats();
    }
    
    public int getNumberofContigs(){
        return contigNo;
    }    
    public Map<NLevel, Integer> getNLevels(){
        return nlevels;
    }
    public long getTotalGCcount(){
        return this.total_gc_count;
    }
    public double getTotalGCpercent(){
        return this.total_gc_percent;
    }
    public double getMean(){
        return mean;
    }
    public int getMedian(){
        return median;
    }
    public int getMin(){
        return this.min;        
    }
    public int getMax(){
        return this.max;        
    }
    private void setGCPercent(){
        this.total_gc_percent = 100*(double)this.total_gc_count / (double)this.getTotalcontigSize();
    }
    private void setBasics(){
        boolean first = true;
        int curr;
        List<ContigRecord> tmplist = new ArrayList();
       
        try(RandomAccessFile out=new RandomAccessFile(cumulativeContigSizeFile,"rw")){            
            out.writeInt(0);
            for(int i=contigLengths.size()-1; i >=0; i--){            
                curr = contigLengths.get(i).getLength();
                if( curr >= level){
                    //sum+=curr;
                    tmplist.add(contigLengths.get(i));
                    contigNo++;
                    totalcontigSize += contigLengths.get(i).getLength();
                    total_gc_count += contigLengths.get(i).getGCCount();
                    //this.cumulativeContigSize[it] = totalcontigSize;
                    out.writeLong(totalcontigSize);                    
                    
                    if(first){
                        min =  max = curr;                    
                        first= false;
                    }
                    else{
                        if(curr < min)
                            min = curr;
                        if(curr > max)
                            max = curr;
                    }
                }
            }
            out.seek(0);
            out.writeInt(contigNo);
        }
        catch(Exception e){e.printStackTrace();}
        
        // set mean 
        mean = (double)totalcontigSize / (double)contigNo;
        if(!tmplist.isEmpty())
            median =  tmplist.get(tmplist.size()/2).getLength();
        else
            median = -1;
        // set gc percent
        total_gc_percent = Utilities.calcPercentage(total_gc_count, totalcontigSize);
//        Utilities.dataholder.getLength(level).setCumulativeContigSize(cumulativeContigSize);
    }
    private void computeStats(){

        setBasics();
        NLevel Ngoal=NLevel.N10;
        LLevel Lgoal=LLevel.L10;        
        double temp=0;
        int count=0;
        for(int i=contigLengths.size()-1; i >=0; i--){            
            if(contigLengths.get(i).getLength() > level){
                count++;
                temp += contigLengths.get(i).getLength() ;
                if(Ngoal!=null && Utilities.calcPercentage(temp, totalcontigSize) >= Ngoal.getThreshold()){
                    nlevels.put(Ngoal, contigLengths.get(i).getLength());
                    llevels.put(Lgoal, count);
                    Ngoal = Ngoal.nextLevel();
                    Lgoal = Lgoal.nextLevel();
                }
            }
        }
        if(Ngoal != null){
            NLevel tmp = Ngoal.prevLevel();
            LLevel tmp2 = Lgoal.prevLevel();
            while(Ngoal !=null){
                nlevels.put(Ngoal, nlevels.get(tmp));
                llevels.put(Lgoal, llevels.get(tmp2));
                Ngoal = Ngoal.nextLevel();
                Lgoal = Lgoal.nextLevel();
            }
        }

    }            
}
