package lc.mecha.lang;

import lc.mecha.log.MechaLogger;

import java.util.*;

/**
 * Count... things.
 *
 * @author Alex Leigh
 */
public class Counter<T> {
    private final HashMap<T, Integer> counts = new HashMap<>();

    public void count(T obj) {
        Integer x = counts.get(obj);
        if (x == null) {
            x = 0;
        }
        counts.put(obj, x + 1);
    }

    public void count(List<T> objs) {
        for (T obj : objs) {
            count(obj);
        }
    }

    // function to sort hashmap by values
    public HashMap<T, Integer> sortByValue(HashMap<T, Integer> hm) {
        // Create a list from elements of HashMap
        List<Map.Entry<T, Integer>> list = new LinkedList<>(hm.entrySet());

        // Sort the list
        Collections.sort(list, Comparator.comparing(Map.Entry::getValue));
        Collections.reverse(list);

        // put data from sorted list to hashmap
        HashMap<T, Integer> temp = new LinkedHashMap<>();
        for (Map.Entry<T, Integer> aa : list) {
            temp.put(aa.getKey(), aa.getValue());
        }
        return temp;
    }

    public HashMap<T, Integer> getCounts() {
        return sortByValue(counts);
    }

    public void print(MechaLogger log) {
        for (Map.Entry<T, Integer> entry : counts.entrySet()) {
            log.info("Count: {} {}", entry.getKey(), entry.getValue());
        }
    }

    @Override
    public String toString() {
        return "Counter{" +
                "counts=" + counts +
                '}';
    }
}
