/*
 *  Copyright (c) 2017 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 <cstdint>
#include <cstdlib>

#include "api/test/simulated_network.h"
#include "audio/test/audio_end_to_end_test.h"
#include "call/audio_receive_stream.h"
#include "call/audio_send_stream.h"
#include "rtc_base/thread.h"
#include "test/call_test.h"
#include "test/gtest.h"

namespace webrtc {
namespace test {
namespace {

// Wait half a second between stopping sending and stopping receiving audio.
constexpr int kExtraRecordTimeMs = 500;

bool IsNear(int reference, int v) {
  // Margin is 10%.
  const int error = reference / 10 + 1;
  return std::abs(reference - v) <= error;
}

class NoLossTest : public AudioEndToEndTest {
 public:
  const int kTestDurationMs = 8000;
  const int kBytesSent = 69351;
  const int32_t kPacketsSent = 400;
  const int64_t kRttMs = 100;

  NoLossTest() = default;

  BuiltInNetworkBehaviorConfig GetSendTransportConfig() const override {
    BuiltInNetworkBehaviorConfig pipe_config;
    pipe_config.queue_delay_ms = kRttMs / 2;
    return pipe_config;
  }

  void PerformTest() override {
    Thread::SleepMs(kTestDurationMs);
    send_audio_device()->StopRecording();
    // and some extra time to account for network delay.
    Thread::SleepMs(GetSendTransportConfig().queue_delay_ms +
                    kExtraRecordTimeMs);
  }

  void OnStreamsStopped() override {
    AudioSendStream::Stats send_stats = send_stream()->GetStats();
    EXPECT_PRED2(IsNear, kBytesSent, send_stats.payload_bytes_sent);
    EXPECT_PRED2(IsNear, kPacketsSent, send_stats.packets_sent);
    EXPECT_EQ(0, send_stats.packets_lost);
    EXPECT_EQ(0.0f, send_stats.fraction_lost);
    EXPECT_EQ("opus", send_stats.codec_name);
    // send_stats.jitter_ms
    EXPECT_PRED2(IsNear, kRttMs, send_stats.rtt_ms);
    // Send level is 0 because it is cleared in TransmitMixer::StopSend().
    EXPECT_EQ(0, send_stats.audio_level);
    // send_stats.total_input_energy
    // send_stats.total_input_duration
    EXPECT_FALSE(send_stats.apm_statistics.delay_median_ms);
    EXPECT_FALSE(send_stats.apm_statistics.delay_standard_deviation_ms);
    EXPECT_FALSE(send_stats.apm_statistics.echo_return_loss);
    EXPECT_FALSE(send_stats.apm_statistics.echo_return_loss_enhancement);
    EXPECT_FALSE(send_stats.apm_statistics.residual_echo_likelihood);
    EXPECT_FALSE(send_stats.apm_statistics.residual_echo_likelihood_recent_max);

    AudioReceiveStreamInterface::Stats recv_stats =
        receive_stream()->GetStats(/*get_and_clear_legacy_stats=*/true);
    EXPECT_PRED2(IsNear, kBytesSent, recv_stats.payload_bytes_received);
    EXPECT_PRED2(IsNear, kPacketsSent, recv_stats.packets_received);
    EXPECT_EQ(0, recv_stats.packets_lost);
    EXPECT_EQ("opus", send_stats.codec_name);
    // recv_stats.jitter_ms
    // recv_stats.jitter_buffer_ms
    EXPECT_EQ(20u, recv_stats.jitter_buffer_preferred_ms);
    // recv_stats.delay_estimate_ms
    // Receive level is 0 because it is cleared in Channel::StopPlayout().
    EXPECT_EQ(0, recv_stats.audio_level);
    // recv_stats.total_output_energy
    // recv_stats.total_samples_received
    // recv_stats.total_output_duration
    // recv_stats.concealed_samples
    // recv_stats.expand_rate
    // recv_stats.speech_expand_rate
    EXPECT_EQ(0.0, recv_stats.secondary_decoded_rate);
    EXPECT_EQ(0.0, recv_stats.secondary_discarded_rate);
    EXPECT_EQ(0.0, recv_stats.accelerate_rate);
    EXPECT_EQ(0.0, recv_stats.preemptive_expand_rate);
    EXPECT_EQ(0, recv_stats.decoding_calls_to_silence_generator);
    // recv_stats.decoding_calls_to_neteq
    // recv_stats.decoding_normal
    // recv_stats.decoding_plc
    EXPECT_EQ(0, recv_stats.decoding_cng);
    // recv_stats.decoding_plc_cng
    // recv_stats.decoding_muted_output
    // Capture start time is -1 because we do not have an associated send stream
    // on the receiver side.
    EXPECT_EQ(-1, recv_stats.capture_start_ntp_time_ms);

    // Match these stats between caller and receiver.
    EXPECT_EQ(send_stats.local_ssrc, recv_stats.remote_ssrc);
    EXPECT_EQ(*send_stats.codec_payload_type, *recv_stats.codec_payload_type);
  }
};
}  // namespace

using AudioStatsTest = CallTest;

TEST_F(AudioStatsTest, DISABLED_NoLoss) {
  NoLossTest test;
  RunBaseTest(&test);
}

}  // namespace test
}  // namespace webrtc
