package ru.yandex.webmaster3.core.metrics;

import org.joda.time.DateTime;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author tsyplyaev
 */
public class MetricHistory {
    private final long maxAge, minInterval;
    private final TimeUnit maxAgeTimeUnit, minIntervalTimeUnit;

    private final List<Entry> history = new LinkedList<>();

    public MetricHistory(long maxAge, TimeUnit maxAgeTimeUnit, long minInterval, TimeUnit minIntervalTimeUnit) {
        this.maxAge = maxAge;
        this.maxAgeTimeUnit = maxAgeTimeUnit;
        this.minInterval = minInterval;
        this.minIntervalTimeUnit = minIntervalTimeUnit;
    }

    public void addEntry(Number value) {
        addEntry(DateTime.now(), value);
    }

    public void addEntry(DateTime dateTime, Number value) {
        clearOld();
        if (history.isEmpty() || dateTime.getMillis() - history.get(history.size()-1).getDateTime().getMillis() > minIntervalTimeUnit.toMillis(minInterval)) {
            history.add(new Entry(dateTime, value));
        }
    }

    public List<Entry> getHistory() {
        return history;
    }

    public void clear() {
        history.clear();
    }

    private void clearOld() {
        Iterator<Entry> it = history.iterator();
        long now = DateTime.now().getMillis();

        while (it.hasNext() && now - it.next().getDateTime().getMillis() > maxAgeTimeUnit.toMillis(maxAge)) {
            it.remove();
        }
    }

    public static class Entry {
        private final DateTime dateTime;
        private final Number value;

        public Entry(DateTime dateTime, Number value) {
            this.dateTime = dateTime;
            this.value = value;
        }

        public DateTime getDateTime() {
            return dateTime;
        }

        public Number getValue() {
            return value;
        }
    }
}
