package br.ufrgs.inf.prosoft.tigris.sampling;

import org.apache.commons.math3.stat.descriptive.SummaryStatistics;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class FrequencyDataSet {

    private Map<Granularity, Integer> granularityPopulation = new ConcurrentHashMap<>();
    private SummaryStatistics statistics = new SummaryStatistics();
    private long n;

    public void addItem(Granularity item, double executionTime) {
        granularityPopulation.put(item, granularityPopulation.getOrDefault(item, 0) + 1);
        statistics.addValue(executionTime);
        n++;
    }

    public double getMeanExecutionTime(){
        return statistics.getMean();
    }

    public double getStdExecutionTime(){
        return statistics.getStandardDeviation();
    }

    public long getTotalItems(){
        return n;
    }

    public double getProportion(Granularity granularity){
        Integer occurrences = granularityPopulation.get(granularity);
        if (occurrences == null)
            return 0;
        try {
            return new BigDecimal(occurrences).divide(new BigDecimal(getTotalItems()), MathContext.DECIMAL128).doubleValue();
        } catch (Exception e) {
            return 0;
        }
    }

    public Set<Granularity> getGranularities(){
        return granularityPopulation.keySet();
    }

    public SummaryStatistics getAsDescriptiveStatistics(){
        SummaryStatistics summaryStatistics = new SummaryStatistics();
        for (Map.Entry<Granularity, Integer> populationEntry : granularityPopulation.entrySet()) {
            summaryStatistics.addValue(populationEntry.getValue());
        }
        return summaryStatistics;
    }

    public Map<Granularity, Integer> getTraceFrequency() {
        return granularityPopulation;
    }

    @Override
    public String toString() {
        return "FrequencyDataSet{" +
                "granularityPopulation=" + granularityPopulation +
                ", n=" + n +
                '}';
    }

    public void clear() {
        granularityPopulation.clear();
        statistics.clear();
        n = 0;
    }
}
