package com.knecon.fforesight.service.layoutparser.processor.model;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import lombok.Getter;

@Getter
public class FloatFrequencyCounter {

    Map<Double, Integer> countPerValue = new HashMap<>();
    boolean changed;
    Double mostPopularCache;


    public void add(double value) {

        changed = true;

        if (!countPerValue.containsKey(value)) {
            countPerValue.put(value, 1);
        } else {
            countPerValue.put(value, countPerValue.get(value) + 1);
        }
    }


    public void addAll(Map<Double, Integer> otherCounter) {

        changed = true;

        for (Map.Entry<Double, Integer> entry : otherCounter.entrySet()) {
            if (countPerValue.containsKey(entry.getKey())) {
                countPerValue.put(entry.getKey(), countPerValue.get(entry.getKey()) + entry.getValue());
            } else {
                countPerValue.put(entry.getKey(), entry.getValue());
            }
        }
    }


    public Double getMostPopular() {

        if (changed || mostPopularCache == null) {
            Map.Entry<Double, Integer> mostPopular = null;
            for (Map.Entry<Double, Integer> entry : countPerValue.entrySet()) {
                if (mostPopular == null || entry.getValue() >= mostPopular.getValue()) {
                    mostPopular = entry;
                }
            }
            mostPopularCache = mostPopular != null ? mostPopular.getKey() : 0;
            changed = false;
        }

        return mostPopularCache;
    }


    public List<Double> getValuesInReverseOrder() {

        return countPerValue.keySet()
                .stream()
                .sorted(Collections.reverseOrder())
                .collect(Collectors.toList());
    }


    public Double getHighest() {

        Double highest = null;
        for (Double value : countPerValue.keySet()) {
            if (highest == null || value > highest) {
                highest = value;
            }
        }
        return highest;
    }

}
