/*
 *  Copyright (c) 2023 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/frequency_tracker.h"

#include <cstdint>
#include <cstdlib>
#include <limits>
#include <optional>

#include "api/units/frequency.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "test/gmock.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

using ::testing::AllOf;
using ::testing::Gt;
using ::testing::Lt;

constexpr TimeDelta kWindow = TimeDelta::Millis(500);
constexpr TimeDelta kEpsilon = TimeDelta::Millis(1);

TEST(FrequencyTrackerTest, ReturnsNulloptInitially) {
  Timestamp now = Timestamp::Seconds(12'345);
  FrequencyTracker stats(kWindow);

  EXPECT_EQ(stats.Rate(now), std::nullopt);
}

TEST(FrequencyTrackerTest, ReturnsNulloptAfterSingleDataPoint) {
  Timestamp now = Timestamp::Seconds(12'345);
  FrequencyTracker stats(kWindow);

  stats.Update(now);
  now += TimeDelta::Millis(10);

  EXPECT_EQ(stats.Rate(now), std::nullopt);
}

TEST(FrequencyTrackerTest, ReturnsRateAfterTwoMeasurements) {
  Timestamp now = Timestamp::Seconds(12'345);
  FrequencyTracker stats(kWindow);

  stats.Update(now);
  now += TimeDelta::Millis(1);
  stats.Update(now);

  // 1 event per 1 ms ~= 1'000 events per second.
  EXPECT_EQ(stats.Rate(now), Frequency::Hertz(1'000));
}

TEST(FrequencyTrackerTest, MeasuresConstantRate) {
  const Timestamp start = Timestamp::Seconds(12'345);
  const TimeDelta kInterval = TimeDelta::Millis(10);
  const Frequency kConstantRate = 1 / kInterval;

  Timestamp now = start;
  FrequencyTracker stats(kWindow);

  stats.Update(now);
  Frequency last_error = Frequency::PlusInfinity();
  for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kInterval) {
    SCOPED_TRACE(ToString(i));
    now += kInterval;
    stats.Update(now);

    // Until window is full, rate is measured over a smaller window and might
    // look larger than the constant rate.
    std::optional<Frequency> rate = stats.Rate(now);
    ASSERT_GE(rate, kConstantRate);

    // Expect the estimation error to decrease as the window is extended.
    Frequency error = *rate - kConstantRate;
    EXPECT_LE(error, last_error);
    last_error = error;
  }

  // Once window is full, rate measurment should be stable.
  for (TimeDelta i = TimeDelta::Zero(); i < kInterval;
       i += TimeDelta::Millis(1)) {
    SCOPED_TRACE(ToString(i));
    EXPECT_EQ(stats.Rate(now + i), kConstantRate);
  }
}

TEST(FrequencyTrackerTest, CanMeasureFractionalRate) {
  const TimeDelta kInterval = TimeDelta::Millis(134);
  Timestamp now = Timestamp::Seconds(12'345);
  // FrequencyTracker counts number of events in the window, thus when window is
  // fraction of 1 second, number of events per second would always be integer.
  const TimeDelta window = TimeDelta::Seconds(2);

  FrequencyTracker framerate(window);
  framerate.Update(now);
  for (TimeDelta i = TimeDelta::Zero(); i < window; i += kInterval) {
    now += kInterval;
    framerate.Update(now);
  }

  // Should be aproximitly 7.5 fps
  EXPECT_THAT(framerate.Rate(now),
              AllOf(Gt(Frequency::Hertz(7)), Lt(Frequency::Hertz(8))));
}

TEST(FrequencyTrackerTest, IncreasingThenDecreasingRate) {
  const int64_t kLargeSize = 1'500;
  const int64_t kSmallSize = 300;
  const TimeDelta kLargeInterval = TimeDelta::Millis(10);
  const TimeDelta kSmallInterval = TimeDelta::Millis(2);

  Timestamp now = Timestamp::Seconds(12'345);
  FrequencyTracker stats(kWindow);

  stats.Update(kLargeSize, now);
  for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kLargeInterval) {
    SCOPED_TRACE(ToString(i));
    now += kLargeInterval;
    stats.Update(kLargeSize, now);
  }
  std::optional<Frequency> last_rate = stats.Rate(now);
  EXPECT_EQ(last_rate, kLargeSize / kLargeInterval);

  // Decrease rate with smaller measurments.
  for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kLargeInterval) {
    SCOPED_TRACE(ToString(i));
    now += kLargeInterval;
    stats.Update(kSmallSize, now);

    std::optional<Frequency> rate = stats.Rate(now);
    EXPECT_LT(rate, last_rate);

    last_rate = rate;
  }
  EXPECT_EQ(last_rate, kSmallSize / kLargeInterval);

  // Increase rate with more frequent measurments.
  for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kSmallInterval) {
    SCOPED_TRACE(ToString(i));
    now += kSmallInterval;
    stats.Update(kSmallSize, now);

    std::optional<Frequency> rate = stats.Rate(now);
    EXPECT_GE(rate, last_rate);

    last_rate = rate;
  }
  EXPECT_EQ(last_rate, kSmallSize / kSmallInterval);
}

TEST(FrequencyTrackerTest, ResetAfterSilence) {
  const TimeDelta kInterval = TimeDelta::Millis(10);
  const int64_t kPixels = 640 * 360;

  Timestamp now = Timestamp::Seconds(12'345);
  FrequencyTracker pixel_rate(kWindow);

  // Feed data until window has been filled.
  pixel_rate.Update(kPixels, now);
  for (TimeDelta i = TimeDelta::Zero(); i < kWindow; i += kInterval) {
    now += kInterval;
    pixel_rate.Update(kPixels, now);
  }
  ASSERT_GT(pixel_rate.Rate(now), Frequency::Zero());

  now += kWindow + kEpsilon;
  // Silence over window size should trigger auto reset for coming sample.
  EXPECT_EQ(pixel_rate.Rate(now), std::nullopt);
  pixel_rate.Update(kPixels, now);
  // Single measurment after reset is not enough to estimate the rate.
  EXPECT_EQ(pixel_rate.Rate(now), std::nullopt);

  // Manual reset, add the same check again.
  pixel_rate.Reset();
  EXPECT_EQ(pixel_rate.Rate(now), std::nullopt);
  now += kInterval;
  pixel_rate.Update(kPixels, now);
  EXPECT_EQ(pixel_rate.Rate(now), std::nullopt);
}

TEST(FrequencyTrackerTest, ReturnsNulloptWhenOverflows) {
  Timestamp now = Timestamp::Seconds(12'345);
  FrequencyTracker stats(kWindow);

  int64_t very_large_number = std::numeric_limits<int64_t>::max();
  stats.Update(very_large_number, now);
  now += kEpsilon;
  stats.Update(very_large_number, now);

  EXPECT_EQ(stats.Rate(now), std::nullopt);
}

}  // namespace
}  // namespace webrtc
