package ru.yandex.webmaster3.storage.history;

import org.apache.commons.lang3.tuple.Triple;
import org.joda.time.DateTime;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * @author tsyplyaev
 */
public class Timeline<T extends Comparable> {
    private final Set<T> dates = new TreeSet<>();

    public Timeline() {
    }

    public Timeline(Collection<T> dates) {
        addAll(dates);
    }

    public Timeline(List<Triple<Integer, T, Long>> data) {
        addAll(data.stream().map(Triple::getMiddle).collect(Collectors.toList()));
    }

    public void addAll(Collection<T> dates) {
        this.dates.addAll(dates);
    }

    public List<Point<T, Long>> complete(Map<T, Long> values) {
        TreeMap<T, Long> sortedValues = new TreeMap<>(values);
        for (T date : dates) {
            if (!sortedValues.containsKey(date)) {
                sortedValues.put(date, 0L);
            }
        }
        return toPoints(sortedValues);
    }

    public List<Point<T, Long>> completeIfNotEmpty(Map<T, Long> values) {
        if (values.isEmpty()) {
            return Collections.emptyList();
        }

        return complete(values);
    }

    public List<Point<T, Long>> toPoints(Map<T, Long> values) {
        return values.entrySet().stream()
                .map(e -> new Point<>(e.getKey(), e.getValue()))
                .sorted((p1, p2) -> p1.getTime().compareTo(p2.getTime()))
                .collect(Collectors.toList());
    }

    public static Timeline<DateTime> of(List<IndexingHistoryPoint> data) {
        return new Timeline<>(data.stream().map(IndexingHistoryPoint::getDate).collect(Collectors.toList()));
    }

    /*
    public Map<Integer, List<Point<T, Long>>> complete(List<Triple<Integer, T, Long>> data) {
        Map<Integer, List<Triple<Integer, T, Long>>> triples = data.stream().collect(Collectors.groupingBy(Triple::getLeft, Collectors.toList()));
        Map<Integer, Map<T, Long>> byDate = triples.entrySet().stream().collect(Collectors.toMap(
                e -> e.getKey(),
                e -> new TreeMap<T, Long>(
                        e.getValue().stream().collect(Collectors.groupingBy(Triple::getMiddle, Collectors.summingLong(Triple::getRight)))
                )
        ));

        Map<Integer, List<Point<T, Long>>> res = byDate.entrySet().stream().collect(Collectors.toMap(
                e -> e.getKey(),
                e -> complete(e.getValue()))
        );
        return res;
    }*/
}
