/*
 *  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/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);
    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();
      }
    }
    transport_feedback_.AddPacket(packet.ssrc, packet.transport_seq_no,
                                  packet.size + packet.overhead, probe_info,
                                  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
