/*
 *  Copyright (c) 2016 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 "call/flexfec_receive_stream.h"

#include <cstdint>
#include <memory>
#include <vector>

#include "absl/memory/memory.h"
#include "api/array_view.h"
#include "api/call/transport.h"
#include "api/rtp_headers.h"
#include "api/rtp_parameters.h"
#include "call/flexfec_receive_stream_impl.h"
#include "call/rtp_stream_receiver_controller.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
#include "modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "modules/utility/include/mock/mock_process_thread.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/mock_transport.h"

namespace webrtc {

namespace {

using ::testing::_;

constexpr uint8_t kFlexfecPlType = 118;
constexpr uint8_t kFlexfecSsrc[] = {0x00, 0x00, 0x00, 0x01};
constexpr uint8_t kMediaSsrc[] = {0x00, 0x00, 0x00, 0x02};

FlexfecReceiveStream::Config CreateDefaultConfig(
    Transport* rtcp_send_transport) {
  FlexfecReceiveStream::Config config(rtcp_send_transport);
  config.payload_type = kFlexfecPlType;
  config.remote_ssrc = ByteReader<uint32_t>::ReadBigEndian(kFlexfecSsrc);
  config.protected_media_ssrcs = {
      ByteReader<uint32_t>::ReadBigEndian(kMediaSsrc)};
  EXPECT_TRUE(config.IsCompleteAndEnabled());
  return config;
}

RtpPacketReceived ParsePacket(rtc::ArrayView<const uint8_t> packet) {
  RtpPacketReceived parsed_packet(nullptr);
  EXPECT_TRUE(parsed_packet.Parse(packet));
  return parsed_packet;
}

}  // namespace

TEST(FlexfecReceiveStreamConfigTest, IsCompleteAndEnabled) {
  MockTransport rtcp_send_transport;
  FlexfecReceiveStream::Config config(&rtcp_send_transport);

  config.local_ssrc = 18374743;
  config.rtcp_mode = RtcpMode::kCompound;
  config.transport_cc = true;
  config.rtp_header_extensions.emplace_back(TransportSequenceNumber::kUri, 7);
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.payload_type = 123;
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.remote_ssrc = 238423838;
  EXPECT_FALSE(config.IsCompleteAndEnabled());

  config.protected_media_ssrcs.push_back(138989393);
  EXPECT_TRUE(config.IsCompleteAndEnabled());

  config.protected_media_ssrcs.push_back(33423423);
  EXPECT_FALSE(config.IsCompleteAndEnabled());
}

class FlexfecReceiveStreamTest : public ::testing::Test {
 protected:
  FlexfecReceiveStreamTest()
      : config_(CreateDefaultConfig(&rtcp_send_transport_)) {
    EXPECT_CALL(process_thread_, RegisterModule(_, _)).Times(1);
    receive_stream_ = absl::make_unique<FlexfecReceiveStreamImpl>(
        Clock::GetRealTimeClock(), &rtp_stream_receiver_controller_, config_,
        &recovered_packet_receiver_, &rtt_stats_, &process_thread_);
  }

  ~FlexfecReceiveStreamTest() {
    EXPECT_CALL(process_thread_, DeRegisterModule(_)).Times(1);
  }

  MockTransport rtcp_send_transport_;
  FlexfecReceiveStream::Config config_;
  MockRecoveredPacketReceiver recovered_packet_receiver_;
  MockRtcpRttStats rtt_stats_;
  MockProcessThread process_thread_;
  RtpStreamReceiverController rtp_stream_receiver_controller_;
  std::unique_ptr<FlexfecReceiveStreamImpl> receive_stream_;
};

TEST_F(FlexfecReceiveStreamTest, ConstructDestruct) {}

// Create a FlexFEC packet that protects a single media packet and ensure
// that the callback is called. Correctness of recovery is checked in the
// FlexfecReceiver unit tests.
TEST_F(FlexfecReceiveStreamTest, RecoversPacket) {
  constexpr uint8_t kFlexfecSeqNum[] = {0x00, 0x01};
  constexpr uint8_t kFlexfecTs[] = {0x00, 0x11, 0x22, 0x33};
  constexpr uint8_t kMediaPlType = 107;
  constexpr uint8_t kMediaSeqNum[] = {0x00, 0x02};
  constexpr uint8_t kMediaTs[] = {0xaa, 0xbb, 0xcc, 0xdd};

  // This packet mask protects a single media packet, i.e., the FlexFEC payload
  // is a copy of that media packet. When inserted in the FlexFEC pipeline,
  // it will thus trivially recover the lost media packet.
  constexpr uint8_t kKBit0 = 1 << 7;
  constexpr uint8_t kFlexfecPktMask[] = {kKBit0 | 0x00, 0x01};
  constexpr uint8_t kPayloadLength[] = {0x00, 0x04};
  constexpr uint8_t kSsrcCount = 1;
  constexpr uint8_t kReservedBits = 0x00;
  constexpr uint8_t kPayloadBits = 0x00;
  // clang-format off
  constexpr uint8_t kFlexfecPacket[] = {
      // RTP header.
      0x80,            kFlexfecPlType,  kFlexfecSeqNum[0],  kFlexfecSeqNum[1],
      kFlexfecTs[0],   kFlexfecTs[1],   kFlexfecTs[2],      kFlexfecTs[3],
      kFlexfecSsrc[0], kFlexfecSsrc[1], kFlexfecSsrc[2],    kFlexfecSsrc[3],
      // FlexFEC header.
      0x00,            kMediaPlType,    kPayloadLength[0],  kPayloadLength[1],
      kMediaTs[0],     kMediaTs[1],     kMediaTs[2],        kMediaTs[3],
      kSsrcCount,      kReservedBits,   kReservedBits,      kReservedBits,
      kMediaSsrc[0],   kMediaSsrc[1],   kMediaSsrc[2],      kMediaSsrc[3],
      kMediaSeqNum[0], kMediaSeqNum[1], kFlexfecPktMask[0], kFlexfecPktMask[1],
      // FEC payload.
      kPayloadBits,    kPayloadBits,    kPayloadBits,       kPayloadBits};
  // clang-format on

  ::testing::StrictMock<MockRecoveredPacketReceiver> recovered_packet_receiver;
  EXPECT_CALL(process_thread_, RegisterModule(_, _)).Times(1);
  FlexfecReceiveStreamImpl receive_stream(
      Clock::GetRealTimeClock(), &rtp_stream_receiver_controller_, config_,
      &recovered_packet_receiver, &rtt_stats_, &process_thread_);

  EXPECT_CALL(recovered_packet_receiver,
              OnRecoveredPacket(_, kRtpHeaderSize + kPayloadLength[1]));

  receive_stream.OnRtpPacket(ParsePacket(kFlexfecPacket));

  // Tear-down
  EXPECT_CALL(process_thread_, DeRegisterModule(_)).Times(1);
}

}  // namespace webrtc
