#pragma once

#include "commit_data.h"
#include "commit_loader.h"
#include "metrics.h"
#include "util.h"

#include <maps/libs/chrono/include/time_point.h>
#include <maps/libs/introspection/include/hashing.h>

#include <string>
#include <vector>

namespace maps::wiki::user_edits_metrics {

class MetricsCalculator {
public:
    MetricsCalculator(
        std::chrono::seconds window,
        int singleMetricDepth,
        std::vector<double> quantiles,
        EventToRegions eventToRegions,
        EventToRegions eventToRegionsFromCommits,
        CommitLoader& commitLoader);

    MetricVec calculate(int totalDepth);

private:
    const std::chrono::seconds window_;
    const int singleMetricDepth_;
    const std::vector<double> quantiles_;

    std::map<std::string, chrono::TimePoint> metricStartTimes_;
    EventToRegions eventToRegions_;
    EventToRegions eventToRegionsFromCommits_;
    size_t finishedMetrics_;
    const size_t maxNumberOfQuantileMetrics_;

    CommitLoader& commitLoader_;

    void calculate(MetricVec* metrics, chrono::TimePoint time);
    bool isFinished() const;
};

using RegionUserType = std::pair<std::string, std::string>;
using RegionUserTypeToMetricVec = std::unordered_map<RegionUserType, MetricVec, introspection::Hasher>;

RegionUserTypeToMetricVec getConsolidatedDeployedMetricsWithEstimations(
    const MetricVec& allMetrics,
    chrono::TimePoint calculationDate,
    double quantile,
    bool inTrunk,
    const RegionToEvents& regionToDeployedEvents);

RegionUserTypeToMetricVec getConsolidatedMetricsWithEstimations(
    const MetricVec& allMetrics,
    chrono::TimePoint calculationDate,
    Event event,
    double quantile,
    bool inTrunk,
    const std::set<std::string>& regions);

MetricVec daysOutOfSlaInSlidingWindow(
    const RegionUserTypeToMetricVec& regionUserTypeToMetricVec,
    Event event,
    size_t windowSize,
    chrono::TimePoint calculationDate,
    double quantile,
    bool inTrunk);

MetricVec achievableSlaInSlidingWindow(
    const RegionUserTypeToMetricVec& regionUserTypeToMetricVec,
    Event event,
    size_t windowSize,
    size_t brokenSlaBudget,
    double quantile,
    bool inTrunk);

} // namespace maps::wiki::user_edits_metrics
