/*
 *  Copyright (c) 2015 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 "audio/audio_receive_stream.h"

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "api/environment/environment_factory.h"
#include "api/test/mock_audio_mixer.h"
#include "api/test/mock_frame_decryptor.h"
#include "audio/conversion.h"
#include "audio/mock_voe_channel_proxy.h"
#include "call/rtp_stream_receiver_controller.h"
#include "modules/audio_device/include/mock_audio_device.h"
#include "modules/audio_processing/include/mock_audio_processing.h"
#include "modules/pacing/packet_router.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "rtc_base/time_utils.h"
#include "test/gtest.h"
#include "test/mock_audio_decoder_factory.h"
#include "test/mock_transport.h"
#include "test/run_loop.h"

namespace webrtc {
namespace test {
namespace {

using ::testing::_;
using ::testing::FloatEq;
using ::testing::NiceMock;
using ::testing::Return;

AudioDecodingCallStats MakeAudioDecodeStatsForTest() {
  AudioDecodingCallStats audio_decode_stats;
  audio_decode_stats.calls_to_silence_generator = 234;
  audio_decode_stats.calls_to_neteq = 567;
  audio_decode_stats.decoded_normal = 890;
  audio_decode_stats.decoded_neteq_plc = 123;
  audio_decode_stats.decoded_codec_plc = 124;
  audio_decode_stats.decoded_cng = 456;
  audio_decode_stats.decoded_plc_cng = 789;
  audio_decode_stats.decoded_muted_output = 987;
  return audio_decode_stats;
}

const uint32_t kRemoteSsrc = 1234;
const uint32_t kLocalSsrc = 5678;
const int kJitterBufferDelay = -7;
const int kPlayoutBufferDelay = 302;
const unsigned int kSpeechOutputLevel = 99;
const double kTotalOutputEnergy = 0.25;
const double kTotalOutputDuration = 0.5;
const int64_t kPlayoutNtpTimestampMs = 5678;

const CallReceiveStatistics kCallStats = {678, 234, -12, 567, 78, 890, 123};
const std::pair<int, SdpAudioFormat> kReceiveCodec = {
    123,
    {"codec_name_recv", 96000, 0}};
const NetworkStatistics kNetworkStats = {
    /*currentBufferSize=*/123,
    /*preferredBufferSize=*/456,
    /*jitterPeaksFound=*/false,
    /*totalSamplesReceived=*/789012,
    /*concealedSamples=*/3456,
    /*silentConcealedSamples=*/123,
    /*concealmentEvents=*/456,
    /*jitterBufferDelayMs=*/789,
    /*jitterBufferEmittedCount=*/543,
    /*jitterBufferTargetDelayMs=*/123,
    /*jitterBufferMinimumDelayMs=*/222,
    /*insertedSamplesForDeceleration=*/432,
    /*removedSamplesForAcceleration=*/321,
    /*fecPacketsReceived=*/123,
    /*fecPacketsDiscarded=*/101,
    /*totalProcessingDelayMs=*/154,
    /*packetsDiscarded=*/989,
    /*currentExpandRate=*/789,
    /*currentSpeechExpandRate=*/12,
    /*currentPreemptiveRate=*/345,
    /*currentAccelerateRate =*/678,
    /*currentSecondaryDecodedRate=*/901,
    /*currentSecondaryDiscardedRate=*/0,
    /*meanWaitingTimeMs=*/-1,
    /*maxWaitingTimeMs=*/-1,
    /*packetBufferFlushes=*/0,
    /*delayedPacketOutageSamples=*/0,
    /*relativePacketArrivalDelayMs=*/135,
    /*interruptionCount=*/-1,
    /*totalInterruptionDurationMs=*/-1};
const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();

struct ConfigHelper {
  explicit ConfigHelper(bool use_null_audio_processing)
      : ConfigHelper(rtc::make_ref_counted<MockAudioMixer>(),
                     use_null_audio_processing) {}

  ConfigHelper(rtc::scoped_refptr<MockAudioMixer> audio_mixer,
               bool use_null_audio_processing)
      : audio_mixer_(audio_mixer) {
    using ::testing::Invoke;

    AudioState::Config config;
    config.audio_mixer = audio_mixer_;
    config.audio_processing =
        use_null_audio_processing
            ? nullptr
            : rtc::make_ref_counted<NiceMock<MockAudioProcessing>>();
    config.audio_device_module =
        rtc::make_ref_counted<testing::NiceMock<MockAudioDeviceModule>>();
    audio_state_ = AudioState::Create(config);

    channel_receive_ = new ::testing::StrictMock<MockChannelReceive>();
    EXPECT_CALL(*channel_receive_, SetNACKStatus(true, 15)).Times(1);
    EXPECT_CALL(*channel_receive_, SetRtcpMode(_)).Times(1);
    EXPECT_CALL(*channel_receive_,
                RegisterReceiverCongestionControlObjects(&packet_router_))
        .Times(1);
    EXPECT_CALL(*channel_receive_, ResetReceiverCongestionControlObjects())
        .Times(1);
    EXPECT_CALL(*channel_receive_, SetAssociatedSendChannel(nullptr)).Times(1);
    EXPECT_CALL(*channel_receive_, SetReceiveCodecs(_))
        .WillRepeatedly(Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
          EXPECT_THAT(codecs, ::testing::IsEmpty());
        }));
    EXPECT_CALL(*channel_receive_, GetLocalSsrc())
        .WillRepeatedly(Return(kLocalSsrc));

    stream_config_.rtp.local_ssrc = kLocalSsrc;
    stream_config_.rtp.remote_ssrc = kRemoteSsrc;
    stream_config_.rtp.nack.rtp_history_ms = 300;
    stream_config_.rtcp_send_transport = &rtcp_send_transport_;
    stream_config_.decoder_factory =
        rtc::make_ref_counted<MockAudioDecoderFactory>();
  }

  std::unique_ptr<AudioReceiveStreamImpl> CreateAudioReceiveStream() {
    auto ret = std::make_unique<AudioReceiveStreamImpl>(
        CreateEnvironment(), &packet_router_, stream_config_, audio_state_,
        std::unique_ptr<voe::ChannelReceiveInterface>(channel_receive_));
    ret->RegisterWithTransport(&rtp_stream_receiver_controller_);
    return ret;
  }

  AudioReceiveStreamInterface::Config& config() { return stream_config_; }
  rtc::scoped_refptr<MockAudioMixer> audio_mixer() { return audio_mixer_; }
  MockChannelReceive* channel_receive() { return channel_receive_; }

  void SetupMockForGetStats() {
    using ::testing::DoAll;
    using ::testing::SetArgPointee;

    ASSERT_TRUE(channel_receive_);
    EXPECT_CALL(*channel_receive_, GetRTCPStatistics())
        .WillOnce(Return(kCallStats));
    EXPECT_CALL(*channel_receive_, GetDelayEstimate())
        .WillOnce(Return(kJitterBufferDelay + kPlayoutBufferDelay));
    EXPECT_CALL(*channel_receive_, GetSpeechOutputLevelFullRange())
        .WillOnce(Return(kSpeechOutputLevel));
    EXPECT_CALL(*channel_receive_, GetTotalOutputEnergy())
        .WillOnce(Return(kTotalOutputEnergy));
    EXPECT_CALL(*channel_receive_, GetTotalOutputDuration())
        .WillOnce(Return(kTotalOutputDuration));
    EXPECT_CALL(*channel_receive_, GetNetworkStatistics(_))
        .WillOnce(Return(kNetworkStats));
    EXPECT_CALL(*channel_receive_, GetDecodingCallStatistics())
        .WillOnce(Return(kAudioDecodeStats));
    EXPECT_CALL(*channel_receive_, GetReceiveCodec())
        .WillOnce(Return(kReceiveCodec));
    EXPECT_CALL(*channel_receive_, GetCurrentEstimatedPlayoutNtpTimestampMs(_))
        .WillOnce(Return(kPlayoutNtpTimestampMs));
  }

 private:
  PacketRouter packet_router_;
  rtc::scoped_refptr<AudioState> audio_state_;
  rtc::scoped_refptr<MockAudioMixer> audio_mixer_;
  AudioReceiveStreamInterface::Config stream_config_;
  ::testing::StrictMock<MockChannelReceive>* channel_receive_ = nullptr;
  RtpStreamReceiverController rtp_stream_receiver_controller_;
  MockTransport rtcp_send_transport_;
};

const std::vector<uint8_t> CreateRtcpSenderReport() {
  std::vector<uint8_t> packet;
  const size_t kRtcpSrLength = 28;  // In bytes.
  packet.resize(kRtcpSrLength);
  packet[0] = 0x80;  // Version 2.
  packet[1] = 0xc8;  // PT = 200, SR.
  // Length in number of 32-bit words - 1.
  ByteWriter<uint16_t>::WriteBigEndian(&packet[2], 6);
  ByteWriter<uint32_t>::WriteBigEndian(&packet[4], kLocalSsrc);
  return packet;
}
}  // namespace

TEST(AudioReceiveStreamTest, ConfigToString) {
  AudioReceiveStreamInterface::Config config;
  config.rtp.remote_ssrc = kRemoteSsrc;
  config.rtp.local_ssrc = kLocalSsrc;
  config.rtp.rtcp_mode = RtcpMode::kOff;
  EXPECT_EQ(
      "{rtp: {remote_ssrc: 1234, local_ssrc: 5678, nack: "
      "{rtp_history_ms: 0}, rtcp: off}, "
      "rtcp_send_transport: null}",
      config.ToString());
}

TEST(AudioReceiveStreamTest, ConstructDestruct) {
  test::RunLoop loop;
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(use_null_audio_processing);
    auto recv_stream = helper.CreateAudioReceiveStream();
    recv_stream->UnregisterFromTransport();
  }
}

TEST(AudioReceiveStreamTest, ReceiveRtcpPacket) {
  test::RunLoop loop;
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(use_null_audio_processing);
    auto recv_stream = helper.CreateAudioReceiveStream();
    std::vector<uint8_t> rtcp_packet = CreateRtcpSenderReport();
    EXPECT_CALL(*helper.channel_receive(),
                ReceivedRTCPPacket(&rtcp_packet[0], rtcp_packet.size()))
        .WillOnce(Return());
    recv_stream->DeliverRtcp(&rtcp_packet[0], rtcp_packet.size());
    recv_stream->UnregisterFromTransport();
  }
}

TEST(AudioReceiveStreamTest, GetStats) {
  test::RunLoop loop;
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(use_null_audio_processing);
    auto recv_stream = helper.CreateAudioReceiveStream();
    helper.SetupMockForGetStats();
    AudioReceiveStreamInterface::Stats stats =
        recv_stream->GetStats(/*get_and_clear_legacy_stats=*/true);
    EXPECT_EQ(kRemoteSsrc, stats.remote_ssrc);
    EXPECT_EQ(kCallStats.payload_bytes_received, stats.payload_bytes_received);
    EXPECT_EQ(kCallStats.header_and_padding_bytes_received,
              stats.header_and_padding_bytes_received);
    EXPECT_EQ(static_cast<uint32_t>(kCallStats.packetsReceived),
              stats.packets_received);
    EXPECT_EQ(kCallStats.cumulativeLost, stats.packets_lost);
    EXPECT_EQ(kReceiveCodec.second.name, stats.codec_name);
    EXPECT_EQ(
        kCallStats.jitterSamples / (kReceiveCodec.second.clockrate_hz / 1000),
        stats.jitter_ms);
    EXPECT_EQ(kNetworkStats.currentBufferSize, stats.jitter_buffer_ms);
    EXPECT_EQ(kNetworkStats.preferredBufferSize,
              stats.jitter_buffer_preferred_ms);
    EXPECT_EQ(static_cast<uint32_t>(kJitterBufferDelay + kPlayoutBufferDelay),
              stats.delay_estimate_ms);
    EXPECT_EQ(static_cast<int32_t>(kSpeechOutputLevel), stats.audio_level);
    EXPECT_EQ(kTotalOutputEnergy, stats.total_output_energy);
    EXPECT_EQ(kNetworkStats.totalSamplesReceived, stats.total_samples_received);
    EXPECT_EQ(kTotalOutputDuration, stats.total_output_duration);
    EXPECT_EQ(kNetworkStats.concealedSamples, stats.concealed_samples);
    EXPECT_EQ(kNetworkStats.concealmentEvents, stats.concealment_events);
    EXPECT_EQ(static_cast<double>(kNetworkStats.jitterBufferDelayMs) /
                  static_cast<double>(rtc::kNumMillisecsPerSec),
              stats.jitter_buffer_delay_seconds);
    EXPECT_EQ(kNetworkStats.jitterBufferEmittedCount,
              stats.jitter_buffer_emitted_count);
    EXPECT_EQ(static_cast<double>(kNetworkStats.jitterBufferTargetDelayMs) /
                  static_cast<double>(rtc::kNumMillisecsPerSec),
              stats.jitter_buffer_target_delay_seconds);
    EXPECT_EQ(static_cast<double>(kNetworkStats.jitterBufferMinimumDelayMs) /
                  static_cast<double>(rtc::kNumMillisecsPerSec),
              stats.jitter_buffer_minimum_delay_seconds);
    EXPECT_EQ(kNetworkStats.insertedSamplesForDeceleration,
              stats.inserted_samples_for_deceleration);
    EXPECT_EQ(kNetworkStats.removedSamplesForAcceleration,
              stats.removed_samples_for_acceleration);
    EXPECT_EQ(kNetworkStats.fecPacketsReceived, stats.fec_packets_received);
    EXPECT_EQ(kNetworkStats.fecPacketsDiscarded, stats.fec_packets_discarded);
    EXPECT_EQ(static_cast<double>(kNetworkStats.totalProcessingDelayUs) /
                  static_cast<double>(rtc::kNumMicrosecsPerSec),
              stats.total_processing_delay_seconds);
    EXPECT_EQ(kNetworkStats.packetsDiscarded, stats.packets_discarded);
    EXPECT_EQ(Q14ToFloat(kNetworkStats.currentExpandRate), stats.expand_rate);
    EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSpeechExpandRate),
              stats.speech_expand_rate);
    EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSecondaryDecodedRate),
              stats.secondary_decoded_rate);
    EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSecondaryDiscardedRate),
              stats.secondary_discarded_rate);
    EXPECT_EQ(Q14ToFloat(kNetworkStats.currentAccelerateRate),
              stats.accelerate_rate);
    EXPECT_EQ(Q14ToFloat(kNetworkStats.currentPreemptiveRate),
              stats.preemptive_expand_rate);
    EXPECT_EQ(kNetworkStats.packetBufferFlushes, stats.jitter_buffer_flushes);
    EXPECT_EQ(kNetworkStats.delayedPacketOutageSamples,
              stats.delayed_packet_outage_samples);
    EXPECT_EQ(static_cast<double>(kNetworkStats.relativePacketArrivalDelayMs) /
                  static_cast<double>(rtc::kNumMillisecsPerSec),
              stats.relative_packet_arrival_delay_seconds);
    EXPECT_EQ(kNetworkStats.interruptionCount, stats.interruption_count);
    EXPECT_EQ(kNetworkStats.totalInterruptionDurationMs,
              stats.total_interruption_duration_ms);

    EXPECT_EQ(kAudioDecodeStats.calls_to_silence_generator,
              stats.decoding_calls_to_silence_generator);
    EXPECT_EQ(kAudioDecodeStats.calls_to_neteq, stats.decoding_calls_to_neteq);
    EXPECT_EQ(kAudioDecodeStats.decoded_normal, stats.decoding_normal);
    EXPECT_EQ(kAudioDecodeStats.decoded_neteq_plc, stats.decoding_plc);
    EXPECT_EQ(kAudioDecodeStats.decoded_codec_plc, stats.decoding_codec_plc);
    EXPECT_EQ(kAudioDecodeStats.decoded_cng, stats.decoding_cng);
    EXPECT_EQ(kAudioDecodeStats.decoded_plc_cng, stats.decoding_plc_cng);
    EXPECT_EQ(kAudioDecodeStats.decoded_muted_output,
              stats.decoding_muted_output);
    EXPECT_EQ(kCallStats.capture_start_ntp_time_ms_,
              stats.capture_start_ntp_time_ms);
    EXPECT_EQ(kPlayoutNtpTimestampMs, stats.estimated_playout_ntp_timestamp_ms);
    recv_stream->UnregisterFromTransport();
  }
}

TEST(AudioReceiveStreamTest, SetGain) {
  test::RunLoop loop;
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(use_null_audio_processing);
    auto recv_stream = helper.CreateAudioReceiveStream();
    EXPECT_CALL(*helper.channel_receive(),
                SetChannelOutputVolumeScaling(FloatEq(0.765f)));
    recv_stream->SetGain(0.765f);
    recv_stream->UnregisterFromTransport();
  }
}

TEST(AudioReceiveStreamTest, StreamsShouldBeAddedToMixerOnceOnStart) {
  test::RunLoop loop;
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper1(use_null_audio_processing);
    ConfigHelper helper2(helper1.audio_mixer(), use_null_audio_processing);
    auto recv_stream1 = helper1.CreateAudioReceiveStream();
    auto recv_stream2 = helper2.CreateAudioReceiveStream();

    EXPECT_CALL(*helper1.channel_receive(), StartPlayout()).Times(1);
    EXPECT_CALL(*helper2.channel_receive(), StartPlayout()).Times(1);
    EXPECT_CALL(*helper1.channel_receive(), StopPlayout()).Times(1);
    EXPECT_CALL(*helper2.channel_receive(), StopPlayout()).Times(1);
    EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream1.get()))
        .WillOnce(Return(true));
    EXPECT_CALL(*helper1.audio_mixer(), AddSource(recv_stream2.get()))
        .WillOnce(Return(true));
    EXPECT_CALL(*helper1.audio_mixer(), RemoveSource(recv_stream1.get()))
        .Times(1);
    EXPECT_CALL(*helper1.audio_mixer(), RemoveSource(recv_stream2.get()))
        .Times(1);

    recv_stream1->Start();
    recv_stream2->Start();

    // One more should not result in any more mixer sources added.
    recv_stream1->Start();

    // Stop stream before it is being destructed.
    recv_stream2->Stop();

    recv_stream1->UnregisterFromTransport();
    recv_stream2->UnregisterFromTransport();
  }
}

TEST(AudioReceiveStreamTest, ReconfigureWithUpdatedConfig) {
  test::RunLoop loop;
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(use_null_audio_processing);
    auto recv_stream = helper.CreateAudioReceiveStream();

    auto new_config = helper.config();

    MockChannelReceive& channel_receive = *helper.channel_receive();

    // TODO(tommi, nisse): This applies new extensions to the internal config,
    // but there's nothing that actually verifies that the changes take effect.
    // In fact Call manages the extensions separately in Call::ReceiveRtpConfig
    // and changing this config value (there seem to be a few copies), doesn't
    // affect that logic.
    recv_stream->ReconfigureForTesting(new_config);

    new_config.decoder_map.emplace(1, SdpAudioFormat("foo", 8000, 1));
    EXPECT_CALL(channel_receive, SetReceiveCodecs(new_config.decoder_map));
    recv_stream->SetDecoderMap(new_config.decoder_map);

    EXPECT_CALL(channel_receive, SetNACKStatus(true, 15 + 1)).Times(1);
    recv_stream->SetNackHistory(300 + 20);

    recv_stream->UnregisterFromTransport();
  }
}

TEST(AudioReceiveStreamTest, ReconfigureWithFrameDecryptor) {
  test::RunLoop loop;
  for (bool use_null_audio_processing : {false, true}) {
    ConfigHelper helper(use_null_audio_processing);
    auto recv_stream = helper.CreateAudioReceiveStream();

    auto new_config_0 = helper.config();
    rtc::scoped_refptr<FrameDecryptorInterface> mock_frame_decryptor_0(
        rtc::make_ref_counted<MockFrameDecryptor>());
    new_config_0.frame_decryptor = mock_frame_decryptor_0;

    // TODO(tommi): While this changes the internal config value, it doesn't
    // actually change what frame_decryptor is used. WebRtcAudioReceiveStream
    // recreates the whole instance in order to change this value.
    // So, it's not clear if changing this post initialization needs to be
    // supported.
    recv_stream->ReconfigureForTesting(new_config_0);

    auto new_config_1 = helper.config();
    rtc::scoped_refptr<FrameDecryptorInterface> mock_frame_decryptor_1(
        rtc::make_ref_counted<MockFrameDecryptor>());
    new_config_1.frame_decryptor = mock_frame_decryptor_1;
    new_config_1.crypto_options.sframe.require_frame_encryption = true;
    recv_stream->ReconfigureForTesting(new_config_1);
    recv_stream->UnregisterFromTransport();
  }
}

}  // namespace test
}  // namespace webrtc
