/*
 *  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 "logging/rtc_event_log/rtc_event_processor.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(
    const std::string& file_name,
    absl::optional<uint32_t> ssrc_filter) {
  auto source = std::unique_ptr<RtcEventLogSource>(new RtcEventLogSource());
  ParsedRtcEventLog parsed_log;
  if (!parsed_log.ParseFile(file_name) ||
      !source->Initialize(parsed_log, ssrc_filter)) {
    std::cerr << "Error while parsing event log, skipping." << std::endl;
    return nullptr;
  }
  return source;
}

std::unique_ptr<RtcEventLogSource> RtcEventLogSource::CreateFromString(
    const std::string& file_contents,
    absl::optional<uint32_t> ssrc_filter) {
  auto source = std::unique_ptr<RtcEventLogSource>(new RtcEventLogSource());
  ParsedRtcEventLog parsed_log;
  if (!parsed_log.ParseString(file_contents) ||
      !source->Initialize(parsed_log, ssrc_filter)) {
    std::cerr << "Error while parsing 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;
}

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);
          }
        }
      };

  // 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);
  }

  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);
  }

  // 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
