/*
 *  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 "modules/audio_coding/neteq/tools/rtc_event_log_source.h"

#include <string.h>

#include <iostream>
#include <limits>
#include <memory>
#include <set>
#include <utility>

#include "absl/strings/string_view.h"
#include "logging/rtc_event_log/rtc_event_processor.h"
#include "modules/audio_coding/neteq/tools/neteq_input.h"
#include "modules/audio_coding/neteq/tools/packet.h"
#include "rtc_base/checks.h"

namespace webrtc {
namespace test {

namespace {
bool ShouldSkipStream(ParsedRtcEventLog::MediaType media_type,
                      uint32_t ssrc,
                      absl::optional<uint32_t> ssrc_filter) {
  if (media_type != ParsedRtcEventLog::MediaType::AUDIO)
    return true;
  if (ssrc_filter.has_value() && ssrc != *ssrc_filter)
    return true;
  return false;
}
}  // namespace

std::unique_ptr<RtcEventLogSource> RtcEventLogSource::CreateFromFile(
    absl::string_view file_name,
    absl::optional<uint32_t> ssrc_filter) {
  auto source = std::unique_ptr<RtcEventLogSource>(new RtcEventLogSource());
  ParsedRtcEventLog parsed_log;
  auto status = parsed_log.ParseFile(file_name);
  if (!status.ok()) {
    std::cerr << "Failed to parse event log: " << status.message() << std::endl;
    std::cerr << "Skipping log." << std::endl;
    return nullptr;
  }
  if (!source->Initialize(parsed_log, ssrc_filter)) {
    std::cerr << "Failed to initialize source from event log, skipping."
              << std::endl;
    return nullptr;
  }
  return source;
}

std::unique_ptr<RtcEventLogSource> RtcEventLogSource::CreateFromString(
    absl::string_view file_contents,
    absl::optional<uint32_t> ssrc_filter) {
  auto source = std::unique_ptr<RtcEventLogSource>(new RtcEventLogSource());
  ParsedRtcEventLog parsed_log;
  auto status = parsed_log.ParseString(file_contents);
  if (!status.ok()) {
    std::cerr << "Failed to parse event log: " << status.message() << std::endl;
    std::cerr << "Skipping log." << std::endl;
    return nullptr;
  }
  if (!source->Initialize(parsed_log, ssrc_filter)) {
    std::cerr << "Failed to initialize source from event log, skipping."
              << std::endl;
    return nullptr;
  }
  return source;
}

RtcEventLogSource::~RtcEventLogSource() {}

std::unique_ptr<Packet> RtcEventLogSource::NextPacket() {
  if (rtp_packet_index_ >= rtp_packets_.size())
    return nullptr;

  std::unique_ptr<Packet> packet = std::move(rtp_packets_[rtp_packet_index_++]);
  return packet;
}

int64_t RtcEventLogSource::NextAudioOutputEventMs() {
  if (audio_output_index_ >= audio_outputs_.size())
    return std::numeric_limits<int64_t>::max();

  int64_t output_time_ms = audio_outputs_[audio_output_index_++];
  return output_time_ms;
}

absl::optional<NetEqInput::SetMinimumDelayInfo>
RtcEventLogSource::NextSetMinimumDelayEvent() {
  if (minimum_delay_index_ >= minimum_delay_.size()) {
    return absl::nullopt;
  }
  return minimum_delay_[minimum_delay_index_++];
}

RtcEventLogSource::RtcEventLogSource() : PacketSource() {}

bool RtcEventLogSource::Initialize(const ParsedRtcEventLog& parsed_log,
                                   absl::optional<uint32_t> ssrc_filter) {
  const auto first_log_end_time_us =
      parsed_log.stop_log_events().empty()
          ? std::numeric_limits<int64_t>::max()
          : parsed_log.stop_log_events().front().log_time_us();

  std::set<uint32_t> packet_ssrcs;
  auto handle_rtp_packet =
      [this, first_log_end_time_us,
       &packet_ssrcs](const webrtc::LoggedRtpPacketIncoming& incoming) {
        if (!filter_.test(incoming.rtp.header.payloadType) &&
            incoming.log_time_us() < first_log_end_time_us) {
          rtp_packets_.emplace_back(std::make_unique<Packet>(
              incoming.rtp.header, incoming.rtp.total_length,
              incoming.rtp.total_length - incoming.rtp.header_length,
              static_cast<double>(incoming.log_time_ms())));
          packet_ssrcs.insert(rtp_packets_.back()->header().ssrc);
        }
      };

  std::set<uint32_t> ignored_ssrcs;
  auto handle_audio_playout =
      [this, first_log_end_time_us, &packet_ssrcs,
       &ignored_ssrcs](const webrtc::LoggedAudioPlayoutEvent& audio_playout) {
        if (audio_playout.log_time_us() < first_log_end_time_us) {
          if (packet_ssrcs.count(audio_playout.ssrc) > 0) {
            audio_outputs_.emplace_back(audio_playout.log_time_ms());
          } else {
            ignored_ssrcs.insert(audio_playout.ssrc);
          }
        }
      };

  auto handle_neteq_set_minimum_delay =
      [this, first_log_end_time_us, &packet_ssrcs](
          const webrtc::LoggedNetEqSetMinimumDelayEvent minimum_delay_event) {
        if (minimum_delay_event.log_time_us() < first_log_end_time_us) {
          if (packet_ssrcs.count(minimum_delay_event.remote_ssrc) > 0) {
            minimum_delay_.emplace_back(minimum_delay_event.log_time_ms(),
                                        minimum_delay_event.minimum_delay_ms);
          }
        }
      };

  // This wouldn't be needed if we knew that there was at most one audio stream.
  webrtc::RtcEventProcessor event_processor;
  for (const auto& rtp_packets : parsed_log.incoming_rtp_packets_by_ssrc()) {
    ParsedRtcEventLog::MediaType media_type =
        parsed_log.GetMediaType(rtp_packets.ssrc, webrtc::kIncomingPacket);
    if (ShouldSkipStream(media_type, rtp_packets.ssrc, ssrc_filter)) {
      continue;
    }
    event_processor.AddEvents(rtp_packets.incoming_packets, handle_rtp_packet);
    // If no SSRC filter has been set, use the first SSRC only. The simulator
    // does not work properly with interleaved packets from multiple SSRCs.
    if (!ssrc_filter.has_value()) {
      ssrc_filter = rtp_packets.ssrc;
    }
  }

  for (const auto& audio_playouts : parsed_log.audio_playout_events()) {
    if (ssrc_filter.has_value() && audio_playouts.first != *ssrc_filter)
      continue;
    event_processor.AddEvents(audio_playouts.second, handle_audio_playout);
  }

  for (const auto& neteq_set_minimum_delay_event :
       parsed_log.neteq_set_minimum_delay_events()) {
    if (ssrc_filter.has_value() &&
        neteq_set_minimum_delay_event.first != *ssrc_filter) {
      continue;
    }
    event_processor.AddEvents(neteq_set_minimum_delay_event.second,
                              handle_neteq_set_minimum_delay);
  }

  // Fills in rtp_packets_ and audio_outputs_.
  event_processor.ProcessEventsInOrder();

  for (const auto& ssrc : ignored_ssrcs) {
    std::cout << "Ignoring GetAudio events from SSRC 0x" << std::hex << ssrc
              << " because no packets were found with a matching SSRC."
              << std::endl;
  }

  return true;
}

}  // namespace test
}  // namespace webrtc
