/*
 *  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 <map>
#include <string>
#include <vector>

#include "api/test/mock_audio_mixer.h"
#include "audio/audio_receive_stream.h"
#include "audio/conversion.h"
#include "call/rtp_stream_receiver_controller.h"
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "modules/audio_device/include/mock_audio_device.h"
#include "modules/audio_processing/include/mock_audio_processing.h"
#include "modules/bitrate_controller/include/mock/mock_bitrate_controller.h"
#include "modules/pacing/packet_router.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "test/gtest.h"
#include "test/mock_audio_decoder_factory.h"
#include "test/mock_voe_channel_proxy.h"

namespace webrtc {
namespace test {
namespace {

using testing::_;
using testing::FloatEq;
using testing::Return;
using testing::ReturnRef;

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_plc = 123;
  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 size_t kOneByteExtensionHeaderLength = 4;
const size_t kOneByteExtensionLength = 4;
const int kAudioLevelId = 3;
const int kTransportSequenceNumberId = 4;
const int kJitterBufferDelay = -7;
const int kPlayoutBufferDelay = 302;
const unsigned int kSpeechOutputLevel = 99;
const double kTotalOutputEnergy = 0.25;
const double kTotalOutputDuration = 0.5;

const CallStatistics kCallStats = {
    345,  678,  901, 234, -12, 3456, 7890, 567, 890, 123};
const CodecInst kCodecInst = {
    123, "codec_name_recv", 96000, -187, 0, -103};
const NetworkStatistics kNetworkStats = {
    123, 456, false, 789012, 3456, 123, 456, 0,  {}, 789, 12,
    345, 678, 901,   0,      -1,   -1,  -1,  -1, -1, 0};
const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();

struct ConfigHelper {
  ConfigHelper()
      : ConfigHelper(new rtc::RefCountedObject<MockAudioMixer>()) {}

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

    AudioState::Config config;
    config.audio_mixer = audio_mixer_;
    config.audio_processing = new rtc::RefCountedObject<MockAudioProcessing>();
    config.audio_device_module =
        new rtc::RefCountedObject<testing::NiceMock<MockAudioDeviceModule>>();
    audio_state_ = AudioState::Create(config);

    channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
    EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
    EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1);
    EXPECT_CALL(*channel_proxy_,
        RegisterReceiverCongestionControlObjects(&packet_router_))
            .Times(1);
    EXPECT_CALL(*channel_proxy_, ResetReceiverCongestionControlObjects())
        .Times(1);
    EXPECT_CALL(*channel_proxy_, RegisterTransport(nullptr)).Times(2);
    testing::Expectation expect_set =
        EXPECT_CALL(*channel_proxy_, SetRtcEventLog(&event_log_))
            .Times(1);
    EXPECT_CALL(*channel_proxy_, SetRtcEventLog(testing::IsNull()))
        .Times(1)
        .After(expect_set);
    EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1);
    EXPECT_CALL(*channel_proxy_, SetReceiveCodecs(_))
        .WillRepeatedly(
            Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
              EXPECT_THAT(codecs, testing::IsEmpty());
            }));

    stream_config_.rtp.local_ssrc = kLocalSsrc;
    stream_config_.rtp.remote_ssrc = kRemoteSsrc;
    stream_config_.rtp.nack.rtp_history_ms = 300;
    stream_config_.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
    stream_config_.rtp.extensions.push_back(RtpExtension(
        RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId));
    stream_config_.decoder_factory =
        new rtc::RefCountedObject<MockAudioDecoderFactory>;
  }

  std::unique_ptr<internal::AudioReceiveStream> CreateAudioReceiveStream() {
    return std::unique_ptr<internal::AudioReceiveStream>(
        new internal::AudioReceiveStream(
            &rtp_stream_receiver_controller_,
            &packet_router_,
            stream_config_,
            audio_state_,
            &event_log_,
            std::unique_ptr<voe::ChannelProxy>(channel_proxy_)));
  }

  AudioReceiveStream::Config& config() { return stream_config_; }
  rtc::scoped_refptr<MockAudioMixer> audio_mixer() { return audio_mixer_; }
  MockVoEChannelProxy* channel_proxy() { return channel_proxy_; }

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

    ASSERT_TRUE(channel_proxy_);
    EXPECT_CALL(*channel_proxy_, GetRTCPStatistics())
        .WillOnce(Return(kCallStats));
    EXPECT_CALL(*channel_proxy_, GetDelayEstimate())
        .WillOnce(Return(kJitterBufferDelay + kPlayoutBufferDelay));
    EXPECT_CALL(*channel_proxy_, GetSpeechOutputLevelFullRange())
        .WillOnce(Return(kSpeechOutputLevel));
    EXPECT_CALL(*channel_proxy_, GetTotalOutputEnergy())
        .WillOnce(Return(kTotalOutputEnergy));
    EXPECT_CALL(*channel_proxy_, GetTotalOutputDuration())
        .WillOnce(Return(kTotalOutputDuration));
    EXPECT_CALL(*channel_proxy_, GetNetworkStatistics())
        .WillOnce(Return(kNetworkStats));
    EXPECT_CALL(*channel_proxy_, GetDecodingCallStatistics())
        .WillOnce(Return(kAudioDecodeStats));
    EXPECT_CALL(*channel_proxy_, GetRecCodec(_))
        .WillOnce(DoAll(SetArgPointee<0>(kCodecInst), Return(true)));
  }

 private:
  PacketRouter packet_router_;
  MockRtcEventLog event_log_;
  rtc::scoped_refptr<AudioState> audio_state_;
  rtc::scoped_refptr<MockAudioMixer> audio_mixer_;
  AudioReceiveStream::Config stream_config_;
  testing::StrictMock<MockVoEChannelProxy>* channel_proxy_ = nullptr;
  RtpStreamReceiverController rtp_stream_receiver_controller_;
};

void BuildOneByteExtension(std::vector<uint8_t>::iterator it,
                           int id,
                           uint32_t extension_value,
                           size_t value_length) {
  const uint16_t kRtpOneByteHeaderExtensionId = 0xBEDE;
  ByteWriter<uint16_t>::WriteBigEndian(&(*it), kRtpOneByteHeaderExtensionId);
  it += 2;

  ByteWriter<uint16_t>::WriteBigEndian(&(*it), kOneByteExtensionLength / 4);
  it += 2;
  const size_t kExtensionDataLength = kOneByteExtensionLength - 1;
  uint32_t shifted_value = extension_value
                           << (8 * (kExtensionDataLength - value_length));
  *it = (id << 4) + (static_cast<uint8_t>(value_length) - 1);
  ++it;
  ByteWriter<uint32_t, kExtensionDataLength>::WriteBigEndian(&(*it),
                                                             shifted_value);
}

const std::vector<uint8_t> CreateRtpHeaderWithOneByteExtension(
    int extension_id,
    uint32_t extension_value,
    size_t value_length) {
  std::vector<uint8_t> header;
  header.resize(webrtc::kRtpHeaderSize + kOneByteExtensionHeaderLength +
                kOneByteExtensionLength);
  header[0] = 0x80;   // Version 2.
  header[0] |= 0x10;  // Set extension bit.
  header[1] = 100;    // Payload type.
  header[1] |= 0x80;  // Marker bit is set.
  ByteWriter<uint16_t>::WriteBigEndian(&header[2], 0x1234);  // Sequence number.
  ByteWriter<uint32_t>::WriteBigEndian(&header[4], 0x5678);  // Timestamp.
  ByteWriter<uint32_t>::WriteBigEndian(&header[8], 0x4321);  // SSRC.

  BuildOneByteExtension(header.begin() + webrtc::kRtpHeaderSize, extension_id,
                        extension_value, value_length);
  return header;
}

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) {
  AudioReceiveStream::Config config;
  config.rtp.remote_ssrc = kRemoteSsrc;
  config.rtp.local_ssrc = kLocalSsrc;
  config.rtp.extensions.push_back(
      RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId));
  EXPECT_EQ(
      "{rtp: {remote_ssrc: 1234, local_ssrc: 5678, transport_cc: off, nack: "
      "{rtp_history_ms: 0}, extensions: [{uri: "
      "urn:ietf:params:rtp-hdrext:ssrc-audio-level, id: 3}]}, "
      "rtcp_send_transport: null}",
      config.ToString());
}

TEST(AudioReceiveStreamTest, ConstructDestruct) {
  ConfigHelper helper;
  auto recv_stream = helper.CreateAudioReceiveStream();
}

TEST(AudioReceiveStreamTest, ReceiveRtpPacket) {
  ConfigHelper helper;
  helper.config().rtp.transport_cc = true;
  auto recv_stream = helper.CreateAudioReceiveStream();
  const int kTransportSequenceNumberValue = 1234;
  std::vector<uint8_t> rtp_packet = CreateRtpHeaderWithOneByteExtension(
      kTransportSequenceNumberId, kTransportSequenceNumberValue, 2);
  PacketTime packet_time(5678000, 0);

  RtpPacketReceived parsed_packet;
  ASSERT_TRUE(parsed_packet.Parse(&rtp_packet[0], rtp_packet.size()));
  parsed_packet.set_arrival_time_ms((packet_time.timestamp + 500) / 1000);

  EXPECT_CALL(*helper.channel_proxy(),
              OnRtpPacket(testing::Ref(parsed_packet)));

  recv_stream->OnRtpPacket(parsed_packet);
}

TEST(AudioReceiveStreamTest, ReceiveRtcpPacket) {
  ConfigHelper helper;
  helper.config().rtp.transport_cc = true;
  auto recv_stream = helper.CreateAudioReceiveStream();
  std::vector<uint8_t> rtcp_packet = CreateRtcpSenderReport();
  EXPECT_CALL(*helper.channel_proxy(),
              ReceivedRTCPPacket(&rtcp_packet[0], rtcp_packet.size()))
      .WillOnce(Return(true));
  EXPECT_TRUE(recv_stream->DeliverRtcp(&rtcp_packet[0], rtcp_packet.size()));
}

TEST(AudioReceiveStreamTest, GetStats) {
  ConfigHelper helper;
  auto recv_stream = helper.CreateAudioReceiveStream();
  helper.SetupMockForGetStats();
  AudioReceiveStream::Stats stats = recv_stream->GetStats();
  EXPECT_EQ(kRemoteSsrc, stats.remote_ssrc);
  EXPECT_EQ(static_cast<int64_t>(kCallStats.bytesReceived), stats.bytes_rcvd);
  EXPECT_EQ(static_cast<uint32_t>(kCallStats.packetsReceived),
            stats.packets_rcvd);
  EXPECT_EQ(kCallStats.cumulativeLost, stats.packets_lost);
  EXPECT_EQ(Q8ToFloat(kCallStats.fractionLost), stats.fraction_lost);
  EXPECT_EQ(std::string(kCodecInst.plname), stats.codec_name);
  EXPECT_EQ(kCallStats.extendedMax, stats.ext_seqnum);
  EXPECT_EQ(kCallStats.jitterSamples / (kCodecInst.plfreq / 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(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(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_plc, stats.decoding_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);
}

TEST(AudioReceiveStreamTest, SetGain) {
  ConfigHelper helper;
  auto recv_stream = helper.CreateAudioReceiveStream();
  EXPECT_CALL(*helper.channel_proxy(),
      SetChannelOutputVolumeScaling(FloatEq(0.765f)));
  recv_stream->SetGain(0.765f);
}

TEST(AudioReceiveStreamTest, StreamsShouldBeAddedToMixerOnceOnStart) {
  ConfigHelper helper1;
  ConfigHelper helper2(helper1.audio_mixer());
  auto recv_stream1 = helper1.CreateAudioReceiveStream();
  auto recv_stream2 = helper2.CreateAudioReceiveStream();

  EXPECT_CALL(*helper1.channel_proxy(), StartPlayout()).Times(1);
  EXPECT_CALL(*helper2.channel_proxy(), StartPlayout()).Times(1);
  EXPECT_CALL(*helper1.channel_proxy(), StopPlayout()).Times(1);
  EXPECT_CALL(*helper2.channel_proxy(), 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();
}

TEST(AudioReceiveStreamTest, ReconfigureWithSameConfig) {
  ConfigHelper helper;
  auto recv_stream = helper.CreateAudioReceiveStream();
  recv_stream->Reconfigure(helper.config());
}

TEST(AudioReceiveStreamTest, ReconfigureWithUpdatedConfig) {
  ConfigHelper helper;
  auto recv_stream = helper.CreateAudioReceiveStream();

  auto new_config = helper.config();
  new_config.rtp.local_ssrc = kLocalSsrc + 1;
  new_config.rtp.nack.rtp_history_ms = 300 + 20;
  new_config.rtp.extensions.clear();
  new_config.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelId + 1));
  new_config.rtp.extensions.push_back(RtpExtension(
        RtpExtension::kTransportSequenceNumberUri,
        kTransportSequenceNumberId + 1));
  new_config.decoder_map.emplace(1, SdpAudioFormat("foo", 8000, 1));

  MockVoEChannelProxy& channel_proxy = *helper.channel_proxy();
  EXPECT_CALL(channel_proxy, SetLocalSSRC(kLocalSsrc + 1)).Times(1);
  EXPECT_CALL(channel_proxy, SetNACKStatus(true, 15 + 1)).Times(1);
  EXPECT_CALL(channel_proxy, SetReceiveCodecs(new_config.decoder_map));

  recv_stream->Reconfigure(new_config);
}
}  // namespace test
}  // namespace webrtc
