/*
 *  Copyright 2019 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 "video/quality_limitation_reason_tracker.h"

#include <cstdint>

#include "common_video/include/quality_limitation_reason.h"
#include "system_wrappers/include/clock.h"
#include "test/gtest.h"

namespace webrtc {

class QualityLimitationReasonTrackerTest : public ::testing::Test {
 public:
  QualityLimitationReasonTrackerTest()
      : fake_clock_(1234), tracker_(&fake_clock_) {}

 protected:
  SimulatedClock fake_clock_;
  QualityLimitationReasonTracker tracker_;
};

TEST_F(QualityLimitationReasonTrackerTest, DefaultValues) {
  EXPECT_EQ(QualityLimitationReason::kNone, tracker_.current_reason());
  auto durations_ms = tracker_.DurationsMs();
  EXPECT_EQ(4u, durations_ms.size());
  EXPECT_EQ(0, durations_ms.find(QualityLimitationReason::kNone)->second);
  EXPECT_EQ(0, durations_ms.find(QualityLimitationReason::kCpu)->second);
  EXPECT_EQ(0, durations_ms.find(QualityLimitationReason::kBandwidth)->second);
  EXPECT_EQ(0, durations_ms.find(QualityLimitationReason::kOther)->second);
}

TEST_F(QualityLimitationReasonTrackerTest, NoneDurationIncreasesByDefault) {
  int64_t initial_duration_ms =
      tracker_.DurationsMs()[QualityLimitationReason::kNone];
  fake_clock_.AdvanceTimeMilliseconds(9999);
  EXPECT_EQ(initial_duration_ms + 9999,
            tracker_.DurationsMs()[QualityLimitationReason::kNone]);
}

TEST_F(QualityLimitationReasonTrackerTest,
       RememberDurationAfterSwitchingReason) {
  tracker_.SetReason(QualityLimitationReason::kCpu);
  int64_t initial_duration_ms =
      tracker_.DurationsMs()[QualityLimitationReason::kCpu];
  fake_clock_.AdvanceTimeMilliseconds(50);
  tracker_.SetReason(QualityLimitationReason::kOther);
  fake_clock_.AdvanceTimeMilliseconds(50);
  EXPECT_EQ(initial_duration_ms + 50,
            tracker_.DurationsMs()[QualityLimitationReason::kCpu]);
}

class QualityLimitationReasonTrackerTestWithParamReason
    : public QualityLimitationReasonTrackerTest,
      public ::testing::WithParamInterface<QualityLimitationReason> {
 public:
  QualityLimitationReasonTrackerTestWithParamReason()
      : reason_(GetParam()),
        different_reason_(reason_ != QualityLimitationReason::kCpu
                              ? QualityLimitationReason::kCpu
                              : QualityLimitationReason::kOther) {}

 protected:
  QualityLimitationReason reason_;
  QualityLimitationReason different_reason_;
};

TEST_P(QualityLimitationReasonTrackerTestWithParamReason,
       DurationIncreasesOverTime) {
  int64_t initial_duration_ms = tracker_.DurationsMs()[reason_];
  tracker_.SetReason(reason_);
  EXPECT_EQ(initial_duration_ms, tracker_.DurationsMs()[reason_]);
  fake_clock_.AdvanceTimeMilliseconds(4321);
  EXPECT_EQ(initial_duration_ms + 4321, tracker_.DurationsMs()[reason_]);
}

TEST_P(QualityLimitationReasonTrackerTestWithParamReason,
       SwitchBetweenReasonsBackAndForth) {
  int64_t initial_duration_ms = tracker_.DurationsMs()[reason_];
  // Spend 100 ms in `different_reason_`.
  tracker_.SetReason(different_reason_);
  fake_clock_.AdvanceTimeMilliseconds(100);
  EXPECT_EQ(initial_duration_ms, tracker_.DurationsMs()[reason_]);
  // Spend 50 ms in `reason_`.
  tracker_.SetReason(reason_);
  fake_clock_.AdvanceTimeMilliseconds(50);
  EXPECT_EQ(initial_duration_ms + 50, tracker_.DurationsMs()[reason_]);
  // Spend another 1000 ms in `different_reason_`.
  tracker_.SetReason(different_reason_);
  fake_clock_.AdvanceTimeMilliseconds(1000);
  EXPECT_EQ(initial_duration_ms + 50, tracker_.DurationsMs()[reason_]);
  // Spend another 100 ms in `reason_`.
  tracker_.SetReason(reason_);
  fake_clock_.AdvanceTimeMilliseconds(100);
  EXPECT_EQ(initial_duration_ms + 150, tracker_.DurationsMs()[reason_]);
  // Change reason one last time without advancing time.
  tracker_.SetReason(different_reason_);
  EXPECT_EQ(initial_duration_ms + 150, tracker_.DurationsMs()[reason_]);
}

INSTANTIATE_TEST_SUITE_P(
    All,
    QualityLimitationReasonTrackerTestWithParamReason,
    ::testing::Values(QualityLimitationReason::kNone,       // "/0"
                      QualityLimitationReason::kCpu,        // "/1"
                      QualityLimitationReason::kBandwidth,  // "/2"
                      QualityLimitationReason::kOther));    // "/3"

}  // namespace webrtc
