// Copyright 2022 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_BASE_STATISTICS_H_
#define COBALT_BASE_STATISTICS_H_

#include <algorithm>
#include <functional>
#include <vector>

#include "starboard/types.h"

namespace base {

namespace internal {

// The default function to convert a sample to its value by dividing.
inline int64_t DefaultSampleToValueFunc(int64_t dividend, int64_t divisor) {
  if (divisor == 0) {
    divisor = 1;
  }
  return dividend / divisor;
}

}  // namespace internal

// Track the statistics of a series of generic samples reprensented as
// dividends and divisors in integer types.  The value of a sample is calculated
// by `SampleToValueFunc` using its dividend and divisor.
//
// Example usages:
//   1. Set dividends to bytes in int and divisors to SbTime, to track the
//      statistics of bandwidth.
//   2. Set the divisor to always be 1, to track the statistics of a count or a
//      duration.
//
// Currently the class can produce the following statistics:
//   1. Average, tracked across all samples.
//   2. Median, tracked across the most recent |MaxSamples| samples.
//   3. Min, tracked across all samples.
//   4. Max, tracked across all samples.
//
// Notes:
//   1. The accumulated values are stored in `int64_t`, and it is the user's
//      responsibility to avoid overflow.
//   2. The class isn't multi-thread safe, and it is the user's responsibility
//      to synchronize the usage when necessary.
//   3. Both the dividend and divisor of the samples should ideally be positive,
//      which is NOT enforced by the class.

#if defined(COBALT_BUILD_TYPE_GOLD)

template <typename DividendType, typename DivisorType, int MaxSamples,
          int64_t (*SampleToValueFunc)(int64_t, int64_t) =
              internal::DefaultSampleToValueFunc>
class Statistics {
 public:
  constexpr Statistics() = default;

  void AddSample(DividendType dividend, DivisorType divisor) {}
  int64_t accumulated_dividend() const { return 0; }
  int64_t accumulated_divisor() const { return 1; }
  int64_t average() const { return 0; }
  int64_t min() const { return 0; }
  int64_t max() const { return 0; }

  int64_t GetMedian() const { return 0; }
};

#else  // defined(COBALT_BUILD_TYPE_GOLD)

template <typename DividendType, typename DivisorType, size_t MaxSamples,
          int64_t (*SampleToValueFunc)(int64_t, int64_t) =
              internal::DefaultSampleToValueFunc>
class Statistics {
 public:
  constexpr Statistics() = default;

  void AddSample(DividendType dividend, DivisorType divisor) {
    static_assert(MaxSamples > 0, "MaxSamples has to be greater than 0.");

    auto& current =
        samples_[(first_sample_index_ + number_of_samples_) % MaxSamples];
    if (number_of_samples_ == MaxSamples) {
      first_sample_index_ = (first_sample_index_ + 1) % MaxSamples;
    } else {
      ++number_of_samples_;
    }

    current.dividend = dividend;
    current.divisor = divisor;
    accumulated_dividend_ += dividend;
    accumulated_divisor_ += divisor;

    auto value = GetSampleValue(current);
    if (first_sample_added_) {
      min_ = std::min(min_, value);
      max_ = std::max(max_, value);
    } else {
      min_ = max_ = value;
      first_sample_added_ = true;
    }
  }

  int64_t accumulated_dividend() const { return accumulated_dividend_; }
  int64_t accumulated_divisor() const { return accumulated_divisor_; }

  int64_t average() const {
    return SampleToValueFunc(accumulated_dividend_, accumulated_divisor_);
  }
  int64_t min() const { return min_; }
  int64_t max() const { return max_; }

  // When there are even number of samples in the object, it is implementation
  // specific to pick any number close to the middle, or the median of the
  // numbers close to the middle.  Use {1, 2, 3, 4} as an example, the median
  // can be 3, or 4, or 3.5.
  int64_t GetMedian() const {
    if (number_of_samples_ == 0) {
      return 0;
    }

    std::vector<Sample> copy;
    copy.reserve(number_of_samples_);
    if (first_sample_index_ + number_of_samples_ <= MaxSamples) {
      copy.assign(samples_ + first_sample_index_,
                  samples_ + first_sample_index_ + number_of_samples_);
    } else {
      auto samples_to_copy = number_of_samples_;
      copy.assign(samples_ + first_sample_index_, samples_ + MaxSamples);
      samples_to_copy -= MaxSamples - first_sample_index_;
      copy.insert(copy.end(), samples_, samples_ + samples_to_copy);
    }

    std::nth_element(copy.begin(), copy.begin() + number_of_samples_ / 2,
                     copy.end(), [](const Sample& left, const Sample& right) {
                       return GetSampleValue(left) < GetSampleValue(right);
                     });
    return GetSampleValue(copy[number_of_samples_ / 2]);
  }

 private:
  Statistics(const Statistics&) = delete;
  Statistics& operator=(const Statistics&) = delete;

  struct Sample {
    DividendType dividend = 0;
    DivisorType divisor = 0;
  };

  static int64_t GetSampleValue(const Sample& sample) {
    return SampleToValueFunc(static_cast<int64_t>(sample.dividend),
                             static_cast<int64_t>(sample.divisor));
  }

  bool first_sample_added_ = false;

  int64_t accumulated_dividend_ = 0;
  int64_t accumulated_divisor_ = 0;
  int64_t min_ = 0;
  int64_t max_ = 0;

  Sample samples_[MaxSamples] = {};  // Ring buffer for samples.
  size_t number_of_samples_ = 0;     // Number of samples in |samples_|.
  size_t first_sample_index_ = 0;    // Index of the first sample in |samples_|.
};

#endif  // defined(COBALT_BUILD_TYPE_GOLD)

}  // namespace base

#endif  // COBALT_BASE_STATISTICS_H_
