/*
 *  Copyright (c) 2018 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/audio_coding/neteq/tools/neteq_test_factory.h"

#include <errno.h>
#include <limits.h>  // For ULONG_MAX returned by strtoul.
#include <stdio.h>
#include <stdlib.h>  // For strtoul.

#include <fstream>
#include <iostream>
#include <memory>
#include <set>
#include <string>
#include <utility>

#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/neteq/neteq.h"
#include "modules/audio_coding/neteq/tools/audio_sink.h"
#include "modules/audio_coding/neteq/tools/fake_decode_from_file.h"
#include "modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.h"
#include "modules/audio_coding/neteq/tools/input_audio_file.h"
#include "modules/audio_coding/neteq/tools/neteq_delay_analyzer.h"
#include "modules/audio_coding/neteq/tools/neteq_event_log_input.h"
#include "modules/audio_coding/neteq/tools/neteq_packet_source_input.h"
#include "modules/audio_coding/neteq/tools/neteq_replacement_input.h"
#include "modules/audio_coding/neteq/tools/neteq_stats_getter.h"
#include "modules/audio_coding/neteq/tools/neteq_stats_plotter.h"
#include "modules/audio_coding/neteq/tools/neteq_test.h"
#include "modules/audio_coding/neteq/tools/output_audio_file.h"
#include "modules/audio_coding/neteq/tools/output_wav_file.h"
#include "modules/audio_coding/neteq/tools/rtp_file_source.h"
#include "rtc_base/checks.h"
#include "rtc_base/ref_counted_object.h"
#include "test/function_audio_decoder_factory.h"
#include "test/testsupport/file_utils.h"

namespace webrtc {
namespace test {
namespace {

absl::optional<int> CodecSampleRate(
    uint8_t payload_type,
    webrtc::test::NetEqTestFactory::Config config) {
  if (payload_type == config.pcmu || payload_type == config.pcma ||
      payload_type == config.ilbc || payload_type == config.pcm16b ||
      payload_type == config.cn_nb || payload_type == config.avt)
    return 8000;
  if (payload_type == config.isac || payload_type == config.pcm16b_wb ||
      payload_type == config.g722 || payload_type == config.cn_wb ||
      payload_type == config.avt_16)
    return 16000;
  if (payload_type == config.isac_swb || payload_type == config.pcm16b_swb32 ||
      payload_type == config.cn_swb32 || payload_type == config.avt_32)
    return 32000;
  if (payload_type == config.opus || payload_type == config.pcm16b_swb48 ||
      payload_type == config.cn_swb48 || payload_type == config.avt_48)
    return 48000;
  if (payload_type == config.red)
    return 0;
  return absl::nullopt;
}

}  // namespace

// A callback class which prints whenver the inserted packet stream changes
// the SSRC.
class SsrcSwitchDetector : public NetEqPostInsertPacket {
 public:
  // Takes a pointer to another callback object, which will be invoked after
  // this object finishes. This does not transfer ownership, and null is a
  // valid value.
  explicit SsrcSwitchDetector(NetEqPostInsertPacket* other_callback)
      : other_callback_(other_callback) {}

  void AfterInsertPacket(const NetEqInput::PacketData& packet,
                         NetEq* neteq) override {
    if (last_ssrc_ && packet.header.ssrc != *last_ssrc_) {
      std::cout << "Changing streams from 0x" << std::hex << *last_ssrc_
                << " to 0x" << std::hex << packet.header.ssrc << std::dec
                << " (payload type "
                << static_cast<int>(packet.header.payloadType) << ")"
                << std::endl;
    }
    last_ssrc_ = packet.header.ssrc;
    if (other_callback_) {
      other_callback_->AfterInsertPacket(packet, neteq);
    }
  }

 private:
  NetEqPostInsertPacket* other_callback_;
  absl::optional<uint32_t> last_ssrc_;
};

NetEqTestFactory::NetEqTestFactory() = default;
NetEqTestFactory::~NetEqTestFactory() = default;

NetEqTestFactory::Config::Config() = default;
NetEqTestFactory::Config::Config(const Config& other) = default;
NetEqTestFactory::Config::~Config() = default;

std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTestFromString(
    const std::string& input_string,
    NetEqFactory* factory,
    const Config& config) {
  std::unique_ptr<NetEqInput> input(
      NetEqEventLogInput::CreateFromString(input_string, config.ssrc_filter));
  if (!input) {
    std::cerr << "Error: Cannot parse input string" << std::endl;
    return nullptr;
  }
  return InitializeTest(std::move(input), factory, config);
}

std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTestFromFile(
    const std::string& input_file_name,
    NetEqFactory* factory,
    const Config& config) {
  // Gather RTP header extensions in a map.
  NetEqPacketSourceInput::RtpHeaderExtensionMap rtp_ext_map = {
      {config.audio_level, kRtpExtensionAudioLevel},
      {config.abs_send_time, kRtpExtensionAbsoluteSendTime},
      {config.transport_seq_no, kRtpExtensionTransportSequenceNumber},
      {config.video_content_type, kRtpExtensionVideoContentType},
      {config.video_timing, kRtpExtensionVideoTiming}};

  std::unique_ptr<NetEqInput> input;
  if (RtpFileSource::ValidRtpDump(input_file_name) ||
      RtpFileSource::ValidPcap(input_file_name)) {
    input.reset(new NetEqRtpDumpInput(input_file_name, rtp_ext_map,
                                      config.ssrc_filter));
  } else {
    input.reset(NetEqEventLogInput::CreateFromFile(input_file_name,
                                                   config.ssrc_filter));
  }

  std::cout << "Input file: " << input_file_name << std::endl;
  if (!input) {
    std::cerr << "Error: Cannot open input file" << std::endl;
    return nullptr;
  }
  return InitializeTest(std::move(input), factory, config);
}

std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTest(
    std::unique_ptr<NetEqInput> input,
    NetEqFactory* factory,
    const Config& config) {
  if (input->ended()) {
    std::cerr << "Error: Input is empty" << std::endl;
    return nullptr;
  }

  if (!config.field_trial_string.empty()) {
    field_trials_ =
        std::make_unique<ScopedFieldTrials>(config.field_trial_string);
  }

  // Skip some initial events/packets if requested.
  if (config.skip_get_audio_events > 0) {
    std::cout << "Skipping " << config.skip_get_audio_events
              << " get_audio events" << std::endl;
    if (!input->NextPacketTime() || !input->NextOutputEventTime()) {
      std::cerr << "No events found" << std::endl;
      return nullptr;
    }
    for (int i = 0; i < config.skip_get_audio_events; i++) {
      input->AdvanceOutputEvent();
      if (!input->NextOutputEventTime()) {
        std::cerr << "Not enough get_audio events found" << std::endl;
        return nullptr;
      }
    }
    while (*input->NextPacketTime() < *input->NextOutputEventTime()) {
      input->PopPacket();
      if (!input->NextPacketTime()) {
        std::cerr << "Not enough incoming packets found" << std::endl;
        return nullptr;
      }
    }
  }

  // Check the sample rate.
  absl::optional<int> sample_rate_hz;
  std::set<std::pair<int, uint32_t>> discarded_pt_and_ssrc;
  while (absl::optional<RTPHeader> first_rtp_header = input->NextHeader()) {
    RTC_DCHECK(first_rtp_header);
    sample_rate_hz = CodecSampleRate(first_rtp_header->payloadType, config);
    if (sample_rate_hz) {
      std::cout << "Found valid packet with payload type "
                << static_cast<int>(first_rtp_header->payloadType)
                << " and SSRC 0x" << std::hex << first_rtp_header->ssrc
                << std::dec << std::endl;
      if (config.initial_dummy_packets > 0) {
        std::cout << "Nr of initial dummy packets: "
                  << config.initial_dummy_packets << std::endl;
        input = std::make_unique<InitialPacketInserterNetEqInput>(
            std::move(input), config.initial_dummy_packets, *sample_rate_hz);
      }
      break;
    }
    // Discard this packet and move to the next. Keep track of discarded payload
    // types and SSRCs.
    discarded_pt_and_ssrc.emplace(first_rtp_header->payloadType,
                                  first_rtp_header->ssrc);
    input->PopPacket();
  }
  if (!discarded_pt_and_ssrc.empty()) {
    std::cout << "Discarded initial packets with the following payload types "
                 "and SSRCs:"
              << std::endl;
    for (const auto& d : discarded_pt_and_ssrc) {
      std::cout << "PT " << d.first << "; SSRC 0x" << std::hex
                << static_cast<int>(d.second) << std::dec << std::endl;
    }
  }
  if (!sample_rate_hz) {
    std::cerr << "Cannot find any packets with known payload types"
              << std::endl;
    return nullptr;
  }

  // If an output file is requested, open it.
  std::unique_ptr<AudioSink> output;
  if (!config.output_audio_filename.has_value()) {
    output = std::make_unique<VoidAudioSink>();
    std::cout << "No output audio file" << std::endl;
  } else if (config.output_audio_filename->size() >= 4 &&
             config.output_audio_filename->substr(
                 config.output_audio_filename->size() - 4) == ".wav") {
    // Open a wav file with the known sample rate.
    output = std::make_unique<OutputWavFile>(*config.output_audio_filename,
                                             *sample_rate_hz);
    std::cout << "Output WAV file: " << *config.output_audio_filename
              << std::endl;
  } else {
    // Open a pcm file.
    output = std::make_unique<OutputAudioFile>(*config.output_audio_filename);
    std::cout << "Output PCM file: " << *config.output_audio_filename
              << std::endl;
  }

  NetEqTest::DecoderMap codecs = NetEqTest::StandardDecoderMap();

  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory =
      CreateBuiltinAudioDecoderFactory();

  // Check if a replacement audio file was provided.
  if (config.replacement_audio_file.size() > 0) {
    // Find largest unused payload type.
    int replacement_pt = 127;
    while (codecs.find(replacement_pt) != codecs.end()) {
      --replacement_pt;
      if (replacement_pt <= 0) {
        std::cerr << "Error: Unable to find available replacement payload type"
                  << std::endl;
        return nullptr;
      }
    }

    auto std_set_int32_to_uint8 = [](const std::set<int32_t>& a) {
      std::set<uint8_t> b;
      for (auto& x : a) {
        b.insert(static_cast<uint8_t>(x));
      }
      return b;
    };

    std::set<uint8_t> cn_types = std_set_int32_to_uint8(
        {config.cn_nb, config.cn_wb, config.cn_swb32, config.cn_swb48});
    std::set<uint8_t> forbidden_types =
        std_set_int32_to_uint8({config.g722, config.red, config.avt,
                                config.avt_16, config.avt_32, config.avt_48});
    input.reset(new NetEqReplacementInput(std::move(input), replacement_pt,
                                          cn_types, forbidden_types));

    // Note that capture-by-copy implies that the lambda captures the value of
    // decoder_factory before it's reassigned on the left-hand side.
    decoder_factory = new rtc::RefCountedObject<FunctionAudioDecoderFactory>(
        [decoder_factory, config](
            const SdpAudioFormat& format,
            absl::optional<AudioCodecPairId> codec_pair_id) {
          std::unique_ptr<AudioDecoder> decoder =
              decoder_factory->MakeAudioDecoder(format, codec_pair_id);
          if (!decoder && format.name == "replacement") {
            decoder = std::make_unique<FakeDecodeFromFile>(
                std::make_unique<InputAudioFile>(config.replacement_audio_file),
                format.clockrate_hz, format.num_channels > 1);
          }
          return decoder;
        });

    if (!codecs
             .insert({replacement_pt, SdpAudioFormat("replacement", 48000, 1)})
             .second) {
      std::cerr << "Error: Unable to insert replacement audio codec"
                << std::endl;
      return nullptr;
    }
  }

  // Create a text log output stream if needed.
  std::unique_ptr<std::ofstream> text_log;
  if (config.textlog && config.textlog_filename.has_value()) {
    // Write to file.
    text_log = std::make_unique<std::ofstream>(*config.textlog_filename);
  } else if (config.textlog) {
    // Print to stdout.
    text_log = std::make_unique<std::ofstream>();
    text_log->basic_ios<char>::rdbuf(std::cout.rdbuf());
  }

  NetEqTest::Callbacks callbacks;
  stats_plotter_ = std::make_unique<NetEqStatsPlotter>(
      config.matlabplot, config.pythonplot, config.concealment_events,
      config.plot_scripts_basename.value_or(""));

  ssrc_switch_detector_.reset(
      new SsrcSwitchDetector(stats_plotter_->stats_getter()->delay_analyzer()));
  callbacks.post_insert_packet = ssrc_switch_detector_.get();
  callbacks.get_audio_callback = stats_plotter_->stats_getter();
  callbacks.simulation_ended_callback = stats_plotter_.get();
  NetEq::Config neteq_config;
  neteq_config.sample_rate_hz = *sample_rate_hz;
  neteq_config.max_packets_in_buffer = config.max_nr_packets_in_buffer;
  neteq_config.enable_fast_accelerate = config.enable_fast_accelerate;
  return std::make_unique<NetEqTest>(
      neteq_config, decoder_factory, codecs, std::move(text_log), factory,
      std::move(input), std::move(output), callbacks);
}

}  // namespace test
}  // namespace webrtc
