/*
 *  Copyright 2016 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 "api/stats/rtcstatsreport.h"

#include <sstream>

namespace webrtc {

RTCStatsReport::ConstIterator::ConstIterator(
    const rtc::scoped_refptr<const RTCStatsReport>& report,
    StatsMap::const_iterator it)
    : report_(report),
      it_(it) {
}

RTCStatsReport::ConstIterator::ConstIterator(const ConstIterator&& other)
    : report_(std::move(other.report_)),
      it_(std::move(other.it_)) {
}

RTCStatsReport::ConstIterator::~ConstIterator() {
}

RTCStatsReport::ConstIterator& RTCStatsReport::ConstIterator::operator++() {
  ++it_;
  return *this;
}

RTCStatsReport::ConstIterator& RTCStatsReport::ConstIterator::operator++(int) {
  return ++(*this);
}

const RTCStats& RTCStatsReport::ConstIterator::operator*() const {
  return *it_->second.get();
}

const RTCStats* RTCStatsReport::ConstIterator::operator->() const {
  return it_->second.get();
}

bool RTCStatsReport::ConstIterator::operator==(
    const RTCStatsReport::ConstIterator& other) const {
  return it_ == other.it_;
}

bool RTCStatsReport::ConstIterator::operator!=(
    const RTCStatsReport::ConstIterator& other) const {
  return !(*this == other);
}

rtc::scoped_refptr<RTCStatsReport> RTCStatsReport::Create(
    int64_t timestamp_us) {
  return rtc::scoped_refptr<RTCStatsReport>(
      new rtc::RefCountedObject<RTCStatsReport>(timestamp_us));
}

RTCStatsReport::RTCStatsReport(int64_t timestamp_us)
    : timestamp_us_(timestamp_us) {
}

RTCStatsReport::~RTCStatsReport() {
}

rtc::scoped_refptr<RTCStatsReport> RTCStatsReport::Copy() const {
  rtc::scoped_refptr<RTCStatsReport> copy = Create(timestamp_us_);
  for (auto it = stats_.begin(); it != stats_.end(); ++it) {
    copy->AddStats(it->second->copy());
  }
  return copy;
}

void RTCStatsReport::AddStats(std::unique_ptr<const RTCStats> stats) {
  auto result = stats_.insert(std::make_pair(std::string(stats->id()),
                              std::move(stats)));
  RTC_DCHECK(result.second) <<
      "A stats object with ID " << result.first->second->id() << " is already "
      "present in this stats report.";
}

const RTCStats* RTCStatsReport::Get(const std::string& id) const {
  StatsMap::const_iterator it = stats_.find(id);
  if (it != stats_.cend())
    return it->second.get();
  return nullptr;
}

std::unique_ptr<const RTCStats> RTCStatsReport::Take(const std::string& id) {
  StatsMap::iterator it = stats_.find(id);
  if (it == stats_.end())
    return nullptr;
  std::unique_ptr<const RTCStats> stats = std::move(it->second);
  stats_.erase(it);
  return stats;
}

void RTCStatsReport::TakeMembersFrom(
    rtc::scoped_refptr<RTCStatsReport> victim) {
  for (StatsMap::iterator it = victim->stats_.begin();
       it != victim->stats_.end(); ++it) {
    AddStats(std::unique_ptr<const RTCStats>(it->second.release()));
  }
  victim->stats_.clear();
}

RTCStatsReport::ConstIterator RTCStatsReport::begin() const {
  return ConstIterator(rtc::scoped_refptr<const RTCStatsReport>(this),
                       stats_.cbegin());
}

RTCStatsReport::ConstIterator RTCStatsReport::end() const {
  return ConstIterator(rtc::scoped_refptr<const RTCStatsReport>(this),
                       stats_.cend());
}

std::string RTCStatsReport::ToJson() const {
  std::ostringstream oss;
  ConstIterator it = begin();
  if (it != end()) {
    oss << '[' << it->ToJson();
    for (++it; it != end(); ++it) {
      oss << "," << it->ToJson();
    }
    oss << ']';
  }
  return oss.str();
}

}  // namespace webrtc
