/*
 *  Copyright 2019 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 "rtc_tools/rtc_event_log_visualizer/log_simulation.h"

#include <algorithm>
#include <utility>

#include "logging/rtc_event_log/rtc_event_processor.h"
#include "modules/rtp_rtcp/source/time_util.h"

namespace webrtc {

LogBasedNetworkControllerSimulation::LogBasedNetworkControllerSimulation(
    std::unique_ptr<NetworkControllerFactoryInterface> factory,
    std::function<void(const NetworkControlUpdate&, Timestamp)> update_handler)
    : update_handler_(update_handler), factory_(std::move(factory)) {}

LogBasedNetworkControllerSimulation::~LogBasedNetworkControllerSimulation() {}

void LogBasedNetworkControllerSimulation::HandleStateUpdate(
    const NetworkControlUpdate& update) {
  update_handler_(update, current_time_);
}

void LogBasedNetworkControllerSimulation::ProcessUntil(Timestamp to_time) {
  if (last_process_.IsInfinite()) {
    NetworkControllerConfig config;
    config.constraints.at_time = to_time;
    config.constraints.min_data_rate = DataRate::kbps(30);
    config.constraints.starting_rate = DataRate::kbps(300);
    config.event_log = &null_event_log_;
    controller_ = factory_->Create(config);
  }
  if (last_process_.IsInfinite() ||
      to_time - last_process_ > TimeDelta::seconds(1)) {
    last_process_ = to_time;
    current_time_ = to_time;
    ProcessInterval msg;
    msg.at_time = to_time;
    HandleStateUpdate(controller_->OnProcessInterval(msg));
  } else {
    while (last_process_ + factory_->GetProcessInterval() <= to_time) {
      last_process_ += factory_->GetProcessInterval();
      current_time_ = last_process_;
      ProcessInterval msg;
      msg.at_time = current_time_;
      HandleStateUpdate(controller_->OnProcessInterval(msg));
    }
    current_time_ = to_time;
  }
}

void LogBasedNetworkControllerSimulation::OnProbeCreated(
    const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
  pending_probes_.push_back({probe_cluster, 0, 0});
}

void LogBasedNetworkControllerSimulation::OnPacketSent(
    const LoggedPacketInfo& packet) {
  ProcessUntil(packet.log_packet_time);
  if (packet.has_transport_seq_no) {
    PacedPacketInfo probe_info;
    if (!pending_probes_.empty() &&
        packet.media_type == LoggedMediaType::kVideo) {
      auto& probe = pending_probes_.front();
      probe_info.probe_cluster_id = probe.event.id;
      probe_info.send_bitrate_bps = probe.event.bitrate_bps;
      probe_info.probe_cluster_min_bytes = probe.event.min_bytes;
      probe_info.probe_cluster_min_probes = probe.event.min_packets;
      probe.packets_sent++;
      probe.bytes_sent += packet.size + packet.overhead;
      if (probe.bytes_sent >= probe.event.min_bytes &&
          probe.packets_sent >= probe.event.min_packets) {
        pending_probes_.pop_front();
      }
    }

    RtpPacketSendInfo packet_info;
    packet_info.ssrc = packet.ssrc;
    packet_info.transport_sequence_number = packet.transport_seq_no;
    packet_info.rtp_sequence_number = packet.stream_seq_no;
    packet_info.has_rtp_sequence_number = true;
    packet_info.length = packet.size;
    packet_info.pacing_info = probe_info;
    transport_feedback_.AddPacket(packet_info, packet.overhead,
                                  packet.log_packet_time);
  }
  rtc::SentPacket sent_packet;
  sent_packet.send_time_ms = packet.log_packet_time.ms();
  sent_packet.info.included_in_allocation = true;
  sent_packet.info.packet_size_bytes = packet.size + packet.overhead;
  if (packet.has_transport_seq_no) {
    sent_packet.packet_id = packet.transport_seq_no;
    sent_packet.info.included_in_feedback = true;
  }
  auto msg = transport_feedback_.ProcessSentPacket(sent_packet);
  if (msg)
    HandleStateUpdate(controller_->OnSentPacket(*msg));
}

void LogBasedNetworkControllerSimulation::OnFeedback(
    const LoggedRtcpPacketTransportFeedback& feedback) {
  auto feedback_time = Timestamp::ms(feedback.log_time_ms());
  ProcessUntil(feedback_time);
  auto msg = transport_feedback_.ProcessTransportFeedback(
      feedback.transport_feedback, feedback_time);
  if (msg)
    HandleStateUpdate(controller_->OnTransportPacketsFeedback(*msg));
}

void LogBasedNetworkControllerSimulation::OnReceiverReport(
    const LoggedRtcpPacketReceiverReport& report) {
  if (report.rr.report_blocks().empty())
    return;
  auto report_time = Timestamp::ms(report.log_time_ms());
  ProcessUntil(report_time);
  int packets_delta = 0;
  int lost_delta = 0;
  for (auto& block : report.rr.report_blocks()) {
    auto it = last_report_blocks_.find(block.source_ssrc());
    if (it != last_report_blocks_.end()) {
      packets_delta +=
          block.extended_high_seq_num() - it->second.extended_high_seq_num();
      lost_delta += block.cumulative_lost() - it->second.cumulative_lost();
    }
    last_report_blocks_[block.source_ssrc()] = block;
  }
  if (packets_delta > lost_delta) {
    TransportLossReport msg;
    msg.packets_lost_delta = lost_delta;
    msg.packets_received_delta = packets_delta - lost_delta;
    msg.receive_time = report_time;
    msg.start_time = last_report_block_time_;
    msg.end_time = report_time;
    last_report_block_time_ = report_time;
    HandleStateUpdate(controller_->OnTransportLossReport(msg));
  }

  TimeDelta rtt = TimeDelta::PlusInfinity();
  for (auto& rb : report.rr.report_blocks()) {
    if (rb.last_sr()) {
      uint32_t receive_time_ntp =
          CompactNtp(TimeMicrosToNtp(report.log_time_us()));
      uint32_t rtt_ntp =
          receive_time_ntp - rb.delay_since_last_sr() - rb.last_sr();
      rtt = std::min(rtt, TimeDelta::ms(CompactNtpRttToMs(rtt_ntp)));
    }
  }
  if (rtt.IsFinite()) {
    RoundTripTimeUpdate msg;
    msg.receive_time = report_time;
    msg.round_trip_time = rtt;
    HandleStateUpdate(controller_->OnRoundTripTimeUpdate(msg));
  }
}

void LogBasedNetworkControllerSimulation::OnIceConfig(
    const LoggedIceCandidatePairConfig& candidate) {
  if (candidate.type == IceCandidatePairConfigType::kSelected) {
    auto log_time = Timestamp::us(candidate.log_time_us());
    ProcessUntil(log_time);
    NetworkRouteChange msg;
    msg.at_time = log_time;
    msg.constraints.min_data_rate = DataRate::kbps(30);
    msg.constraints.starting_rate = DataRate::kbps(300);
    msg.constraints.at_time = log_time;
    HandleStateUpdate(controller_->OnNetworkRouteChange(msg));
  }
}

void LogBasedNetworkControllerSimulation::ProcessEventsInLog(
    const ParsedRtcEventLog& parsed_log_) {
  auto packet_infos = parsed_log_.GetOutgoingPacketInfos();
  RtcEventProcessor processor;
  processor.AddEvents(
      parsed_log_.bwe_probe_cluster_created_events(),
      [this](const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
        OnProbeCreated(probe_cluster);
      });
  processor.AddEvents(packet_infos, [this](const LoggedPacketInfo& packet) {
    OnPacketSent(packet);
  });
  processor.AddEvents(
      parsed_log_.transport_feedbacks(PacketDirection::kIncomingPacket),
      [this](const LoggedRtcpPacketTransportFeedback& feedback) {
        OnFeedback(feedback);
      });
  processor.AddEvents(
      parsed_log_.receiver_reports(PacketDirection::kIncomingPacket),
      [this](const LoggedRtcpPacketReceiverReport& report) {
        OnReceiverReport(report);
      });
  processor.AddEvents(parsed_log_.ice_candidate_pair_configs(),
                      [this](const LoggedIceCandidatePairConfig& candidate) {
                        OnIceConfig(candidate);
                      });
  processor.ProcessEventsInOrder();
}

}  // namespace webrtc
