/*
 *  Copyright 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 "pc/rtc_stats_traversal.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "api/stats/rtcstats_objects.h"
#include "rtc_base/checks.h"

namespace webrtc {

namespace {

void TraverseAndTakeVisitedStats(RTCStatsReport* report,
                                 RTCStatsReport* visited_report,
                                 const std::string& current_id) {
  // Mark current stats object as visited by moving it |report| to
  // |visited_report|.
  std::unique_ptr<const RTCStats> current = report->Take(current_id);
  if (!current) {
    // This node has already been visited (or it is an invalid id).
    return;
  }
  std::vector<const std::string*> neighbor_ids =
      GetStatsReferencedIds(*current);
  visited_report->AddStats(std::move(current));

  // Recursively traverse all neighbors.
  for (const auto* neighbor_id : neighbor_ids) {
    TraverseAndTakeVisitedStats(report, visited_report, *neighbor_id);
  }
}

void AddIdIfDefined(const RTCStatsMember<std::string>& id,
                    std::vector<const std::string*>* neighbor_ids) {
  if (id.is_defined())
    neighbor_ids->push_back(&(*id));
}

void AddIdsIfDefined(const RTCStatsMember<std::vector<std::string>>& ids,
                     std::vector<const std::string*>* neighbor_ids) {
  if (ids.is_defined()) {
    for (const std::string& id : *ids)
      neighbor_ids->push_back(&id);
  }
}

}  // namespace

rtc::scoped_refptr<RTCStatsReport> TakeReferencedStats(
    rtc::scoped_refptr<RTCStatsReport> report,
    const std::vector<std::string>& ids) {
  rtc::scoped_refptr<RTCStatsReport> result =
      RTCStatsReport::Create(report->timestamp_us());
  for (const auto& id : ids) {
    TraverseAndTakeVisitedStats(report.get(), result.get(), id);
  }
  return result;
}

std::vector<const std::string*> GetStatsReferencedIds(const RTCStats& stats) {
  std::vector<const std::string*> neighbor_ids;
  const char* type = stats.type();
  if (type == RTCCertificateStats::kType) {
    const auto& certificate = static_cast<const RTCCertificateStats&>(stats);
    AddIdIfDefined(certificate.issuer_certificate_id, &neighbor_ids);
  } else if (type == RTCCodecStats::kType) {
    const auto& codec = static_cast<const RTCCodecStats&>(stats);
    AddIdIfDefined(codec.transport_id, &neighbor_ids);
  } else if (type == RTCDataChannelStats::kType) {
    // RTCDataChannelStats does not have any neighbor references.
  } else if (type == RTCIceCandidatePairStats::kType) {
    const auto& candidate_pair =
        static_cast<const RTCIceCandidatePairStats&>(stats);
    AddIdIfDefined(candidate_pair.transport_id, &neighbor_ids);
    AddIdIfDefined(candidate_pair.local_candidate_id, &neighbor_ids);
    AddIdIfDefined(candidate_pair.remote_candidate_id, &neighbor_ids);
  } else if (type == RTCLocalIceCandidateStats::kType ||
             type == RTCRemoteIceCandidateStats::kType) {
    const auto& local_or_remote_candidate =
        static_cast<const RTCIceCandidateStats&>(stats);
    AddIdIfDefined(local_or_remote_candidate.transport_id, &neighbor_ids);
  } else if (type == RTCMediaStreamStats::kType) {
    const auto& stream = static_cast<const RTCMediaStreamStats&>(stats);
    AddIdsIfDefined(stream.track_ids, &neighbor_ids);
  } else if (type == RTCMediaStreamTrackStats::kType) {
    const auto& track = static_cast<const RTCMediaStreamTrackStats&>(stats);
    AddIdIfDefined(track.media_source_id, &neighbor_ids);
  } else if (type == RTCPeerConnectionStats::kType) {
    // RTCPeerConnectionStats does not have any neighbor references.
  } else if (type == RTCInboundRTPStreamStats::kType) {
    const auto& inbound_rtp =
        static_cast<const RTCInboundRTPStreamStats&>(stats);
    AddIdIfDefined(inbound_rtp.remote_id, &neighbor_ids);
    AddIdIfDefined(inbound_rtp.track_id, &neighbor_ids);
    AddIdIfDefined(inbound_rtp.transport_id, &neighbor_ids);
    AddIdIfDefined(inbound_rtp.codec_id, &neighbor_ids);
  } else if (type == RTCOutboundRTPStreamStats::kType) {
    const auto& outbound_rtp =
        static_cast<const RTCOutboundRTPStreamStats&>(stats);
    AddIdIfDefined(outbound_rtp.remote_id, &neighbor_ids);
    AddIdIfDefined(outbound_rtp.track_id, &neighbor_ids);
    AddIdIfDefined(outbound_rtp.transport_id, &neighbor_ids);
    AddIdIfDefined(outbound_rtp.codec_id, &neighbor_ids);
    AddIdIfDefined(outbound_rtp.media_source_id, &neighbor_ids);
  } else if (type == RTCRemoteInboundRtpStreamStats::kType) {
    const auto& remote_inbound_rtp =
        static_cast<const RTCRemoteInboundRtpStreamStats&>(stats);
    AddIdIfDefined(remote_inbound_rtp.transport_id, &neighbor_ids);
    AddIdIfDefined(remote_inbound_rtp.codec_id, &neighbor_ids);
    AddIdIfDefined(remote_inbound_rtp.local_id, &neighbor_ids);
  } else if (type == RTCRemoteOutboundRtpStreamStats::kType) {
    const auto& remote_outbound_rtp =
        static_cast<const RTCRemoteOutboundRtpStreamStats&>(stats);
    // Inherited from `RTCRTPStreamStats`.
    AddIdIfDefined(remote_outbound_rtp.track_id, &neighbor_ids);
    AddIdIfDefined(remote_outbound_rtp.transport_id, &neighbor_ids);
    AddIdIfDefined(remote_outbound_rtp.codec_id, &neighbor_ids);
    // Direct members of `RTCRemoteOutboundRtpStreamStats`.
    AddIdIfDefined(remote_outbound_rtp.local_id, &neighbor_ids);
  } else if (type == RTCAudioSourceStats::kType ||
             type == RTCVideoSourceStats::kType) {
    // RTC[Audio/Video]SourceStats does not have any neighbor references.
  } else if (type == RTCTransportStats::kType) {
    // RTCTransportStats does not have any neighbor references.
    const auto& transport = static_cast<const RTCTransportStats&>(stats);
    AddIdIfDefined(transport.rtcp_transport_stats_id, &neighbor_ids);
    AddIdIfDefined(transport.selected_candidate_pair_id, &neighbor_ids);
    AddIdIfDefined(transport.local_certificate_id, &neighbor_ids);
    AddIdIfDefined(transport.remote_certificate_id, &neighbor_ids);
  } else {
    RTC_NOTREACHED() << "Unrecognized type: " << type;
  }
  return neighbor_ids;
}

}  // namespace webrtc
