/*
 *  Copyright (c) 2014 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 "modules/rtp_rtcp/include/remote_ntp_time_estimator.h"

#include "absl/types/optional.h"
#include "modules/rtp_rtcp/source/ntp_time_util.h"
#include "system_wrappers/include/clock.h"
#include "system_wrappers/include/ntp_time.h"
#include "test/gmock.h"
#include "test/gtest.h"

namespace webrtc {
namespace {

constexpr TimeDelta kTestRtt = TimeDelta::Millis(10);
constexpr Timestamp kLocalClockInitialTime = Timestamp::Millis(123);
constexpr Timestamp kRemoteClockInitialTime = Timestamp::Millis(373);
constexpr uint32_t kTimestampOffset = 567;
constexpr int64_t kRemoteToLocalClockOffsetNtp =
    ToNtpUnits(kLocalClockInitialTime - kRemoteClockInitialTime);

class RemoteNtpTimeEstimatorTest : public ::testing::Test {
 protected:
  void AdvanceTime(TimeDelta delta) {
    local_clock_.AdvanceTime(delta);
    remote_clock_.AdvanceTime(delta);
  }

  uint32_t GetRemoteTimestamp() {
    return static_cast<uint32_t>(remote_clock_.TimeInMilliseconds()) * 90 +
           kTimestampOffset;
  }

  void SendRtcpSr() {
    uint32_t rtcp_timestamp = GetRemoteTimestamp();
    NtpTime ntp = remote_clock_.CurrentNtpTime();

    AdvanceTime(kTestRtt / 2);
    EXPECT_TRUE(estimator_.UpdateRtcpTimestamp(kTestRtt, ntp, rtcp_timestamp));
  }

  void SendRtcpSrInaccurately(TimeDelta ntp_error, TimeDelta networking_delay) {
    uint32_t rtcp_timestamp = GetRemoteTimestamp();
    int64_t ntp_error_fractions = ToNtpUnits(ntp_error);
    NtpTime ntp(static_cast<uint64_t>(remote_clock_.CurrentNtpTime()) +
                ntp_error_fractions);
    AdvanceTime(kTestRtt / 2 + networking_delay);
    EXPECT_TRUE(estimator_.UpdateRtcpTimestamp(kTestRtt, ntp, rtcp_timestamp));
  }

  SimulatedClock local_clock_{kLocalClockInitialTime};
  SimulatedClock remote_clock_{kRemoteClockInitialTime};
  RemoteNtpTimeEstimator estimator_{&local_clock_};
};

TEST_F(RemoteNtpTimeEstimatorTest, FailsWithoutValidNtpTime) {
  EXPECT_FALSE(
      estimator_.UpdateRtcpTimestamp(kTestRtt, NtpTime(), /*rtp_timestamp=*/0));
}

TEST_F(RemoteNtpTimeEstimatorTest, Estimate) {
  // Remote peer sends first RTCP SR.
  SendRtcpSr();

  // Remote sends a RTP packet.
  AdvanceTime(TimeDelta::Millis(15));
  uint32_t rtp_timestamp = GetRemoteTimestamp();
  int64_t capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();

  // Local peer needs at least 2 RTCP SR to calculate the capture time.
  const int64_t kNotEnoughRtcpSr = -1;
  EXPECT_EQ(kNotEnoughRtcpSr, estimator_.Estimate(rtp_timestamp));
  EXPECT_EQ(estimator_.EstimateRemoteToLocalClockOffset(), absl::nullopt);

  AdvanceTime(TimeDelta::Millis(800));
  // Remote sends second RTCP SR.
  SendRtcpSr();

  // Local peer gets enough RTCP SR to calculate the capture time.
  EXPECT_EQ(capture_ntp_time_ms, estimator_.Estimate(rtp_timestamp));
  EXPECT_EQ(estimator_.EstimateRemoteToLocalClockOffset(),
            kRemoteToLocalClockOffsetNtp);
}

TEST_F(RemoteNtpTimeEstimatorTest, AveragesErrorsOut) {
  // Remote peer sends first 10 RTCP SR without errors.
  for (int i = 0; i < 10; ++i) {
    AdvanceTime(TimeDelta::Seconds(1));
    SendRtcpSr();
  }

  AdvanceTime(TimeDelta::Millis(150));
  uint32_t rtp_timestamp = GetRemoteTimestamp();
  int64_t capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();
  // Local peer gets enough RTCP SR to calculate the capture time.
  EXPECT_EQ(capture_ntp_time_ms, estimator_.Estimate(rtp_timestamp));
  EXPECT_EQ(kRemoteToLocalClockOffsetNtp,
            estimator_.EstimateRemoteToLocalClockOffset());

  // Remote sends corrupted RTCP SRs
  AdvanceTime(TimeDelta::Seconds(1));
  SendRtcpSrInaccurately(/*ntp_error=*/TimeDelta::Millis(2),
                         /*networking_delay=*/TimeDelta::Millis(-1));
  AdvanceTime(TimeDelta::Seconds(1));
  SendRtcpSrInaccurately(/*ntp_error=*/TimeDelta::Millis(-2),
                         /*networking_delay=*/TimeDelta::Millis(1));

  // New RTP packet to estimate timestamp.
  AdvanceTime(TimeDelta::Millis(150));
  rtp_timestamp = GetRemoteTimestamp();
  capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();

  // Errors should be averaged out.
  EXPECT_EQ(capture_ntp_time_ms, estimator_.Estimate(rtp_timestamp));
  EXPECT_EQ(kRemoteToLocalClockOffsetNtp,
            estimator_.EstimateRemoteToLocalClockOffset());
}

}  // namespace
}  // namespace webrtc
