package ru.yandex.webmaster3.core.solomon.metric;

import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.function.Function;

/**
 * @author avhaliullin
 */
public class SolomonHistogramImpl<T> implements SolomonHistogram<T> {
    private final NavigableMap<T, SolomonCounter> buckets;

    private SolomonHistogramImpl(NavigableMap<T, SolomonCounter> buckets) {
        this.buckets = buckets;
    }

    @Override
    public void add(T key, long amount) {
        Map.Entry<T, SolomonCounter> entry = buckets.ceilingEntry(key);
        if (entry == null) {
            entry = buckets.lastEntry();
        }
        entry.getValue().add(amount);
    }

    private static <T> SolomonHistogramImpl<T> create(Function<T, SolomonCounter> counterProvider, Collection<T> buckets, NavigableMap<T, SolomonCounter> bucketsMap) {
        for (T bucket : buckets) {
            bucketsMap.put(bucket, counterProvider.apply(bucket));
        }
        return new SolomonHistogramImpl<>(bucketsMap);
    }

    public static <T extends Comparable<? super T>> SolomonHistogramImpl<T> create(Function<T, SolomonCounter> counterProvider, Collection<T> buckets) {
        return create(counterProvider, buckets, new TreeMap<>());
    }

    public static <T> SolomonHistogramImpl<T> create(Function<T, SolomonCounter> counterProvider, Collection<T> buckets, Comparator<? super T> comparator) {
        return create(counterProvider, buckets, new TreeMap<>(comparator));
    }
}
