/*
 *  Copyright (c) 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 "modules/rtp_rtcp/source/rtcp_packet/remote_estimate.h"

#include <cstddef>
#include <cstdint>
#include <functional>
#include <utility>
#include <vector>

#include "api/array_view.h"
#include "api/transport/network_types.h"
#include "api/units/data_rate.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtcp_packet/app.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {
namespace rtcp {
namespace {

constexpr int kFieldValueSize = 3;
constexpr int kFieldSize = 1 + kFieldValueSize;
constexpr DataRate kDataRateResolution = DataRate::KilobitsPerSec(1);
constexpr int64_t kMaxEncoded = (1 << (kFieldValueSize * 8)) - 1;

class DataRateSerializer {
 public:
  DataRateSerializer(
      uint8_t id,
      std::function<DataRate*(NetworkStateEstimate*)> field_getter)
      : id_(id), field_getter_(field_getter) {}

  uint8_t id() const { return id_; }

  void Read(const uint8_t* src, NetworkStateEstimate* target) const {
    int64_t scaled = ByteReader<uint32_t, kFieldValueSize>::ReadBigEndian(src);
    if (scaled == kMaxEncoded) {
      *field_getter_(target) = DataRate::PlusInfinity();
    } else {
      *field_getter_(target) = kDataRateResolution * scaled;
    }
  }

  bool Write(const NetworkStateEstimate& src, uint8_t* target) const {
    auto value = *field_getter_(const_cast<NetworkStateEstimate*>(&src));
    if (value.IsMinusInfinity()) {
      RTC_LOG(LS_WARNING) << "Trying to serialize MinusInfinity";
      return false;
    }
    ByteWriter<uint8_t>::WriteBigEndian(target++, id_);
    int64_t scaled;
    if (value.IsPlusInfinity()) {
      scaled = kMaxEncoded;
    } else {
      scaled = value / kDataRateResolution;
      if (scaled >= kMaxEncoded) {
        scaled = kMaxEncoded;
        RTC_LOG(LS_WARNING) << ToString(value) << " is larger than max ("
                            << ToString(kMaxEncoded * kDataRateResolution)
                            << "), encoded as PlusInfinity.";
      }
    }
    ByteWriter<uint32_t, kFieldValueSize>::WriteBigEndian(target, scaled);
    return true;
  }

 private:
  const uint8_t id_;
  const std::function<DataRate*(NetworkStateEstimate*)> field_getter_;
};

class RemoteEstimateSerializerImpl : public RemoteEstimateSerializer {
 public:
  explicit RemoteEstimateSerializerImpl(std::vector<DataRateSerializer> fields)
      : fields_(fields) {}

  Buffer Serialize(const NetworkStateEstimate& src) const override {
    size_t max_size = fields_.size() * kFieldSize;
    size_t size = 0;
    Buffer buf(max_size);
    for (const auto& field : fields_) {
      if (field.Write(src, buf.data() + size)) {
        size += kFieldSize;
      }
    }
    buf.SetSize(size);
    return buf;
  }

  bool Parse(ArrayView<const uint8_t> src,
             NetworkStateEstimate* target) const override {
    if (src.size() % kFieldSize != 0)
      return false;
    RTC_DCHECK_EQ(src.size() % kFieldSize, 0);
    for (const uint8_t* data_ptr = src.data(); data_ptr < src.end();
         data_ptr += kFieldSize) {
      uint8_t field_id = ByteReader<uint8_t>::ReadBigEndian(data_ptr);
      for (const auto& field : fields_) {
        if (field.id() == field_id) {
          field.Read(data_ptr + 1, target);
          break;
        }
      }
    }
    return true;
  }

 private:
  const std::vector<DataRateSerializer> fields_;
};

}  // namespace

const RemoteEstimateSerializer* GetRemoteEstimateSerializer() {
  using E = NetworkStateEstimate;
  static auto* serializer = new RemoteEstimateSerializerImpl({
      {1, [](E* e) { return &e->link_capacity_lower; }},
      {2, [](E* e) { return &e->link_capacity_upper; }},
  });
  return serializer;
}

RemoteEstimate::RemoteEstimate() : serializer_(GetRemoteEstimateSerializer()) {
  SetSubType(kSubType);
  SetName(kName);
  SetSenderSsrc(0);
}

RemoteEstimate::RemoteEstimate(App&& app)
    : App(std::move(app)), serializer_(GetRemoteEstimateSerializer()) {}

bool RemoteEstimate::ParseData() {
  return serializer_->Parse({data(), data_size()}, &estimate_);
}

void RemoteEstimate::SetEstimate(NetworkStateEstimate estimate) {
  estimate_ = estimate;
  auto buf = serializer_->Serialize(estimate);
  SetData(buf.data(), buf.size());
}

}  // namespace rtcp
}  // namespace webrtc
