/*
 *  Copyright 2020 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 "call/adaptation/video_source_restrictions.h"

#include <algorithm>
#include <cstddef>
#include <limits>
#include <optional>
#include <string>
#include <utility>

#include "rtc_base/checks.h"
#include "rtc_base/strings/string_builder.h"

namespace webrtc {

VideoSourceRestrictions::VideoSourceRestrictions()
    : max_pixels_per_frame_(std::nullopt),
      target_pixels_per_frame_(std::nullopt),
      max_frame_rate_(std::nullopt) {}

VideoSourceRestrictions::VideoSourceRestrictions(
    std::optional<size_t> max_pixels_per_frame,
    std::optional<size_t> target_pixels_per_frame,
    std::optional<double> max_frame_rate)
    : max_pixels_per_frame_(std::move(max_pixels_per_frame)),
      target_pixels_per_frame_(std::move(target_pixels_per_frame)),
      max_frame_rate_(std::move(max_frame_rate)) {
  RTC_DCHECK(!max_pixels_per_frame_.has_value() ||
             max_pixels_per_frame_.value() <
                 static_cast<size_t>(std::numeric_limits<int>::max()));
  RTC_DCHECK(!max_frame_rate_.has_value() ||
             max_frame_rate_.value() < std::numeric_limits<int>::max());
  RTC_DCHECK(!max_frame_rate_.has_value() || max_frame_rate_.value() > 0.0);
}

std::string VideoSourceRestrictions::ToString() const {
  StringBuilder ss;
  ss << "{";
  if (max_frame_rate_)
    ss << " max_fps=" << max_frame_rate_.value();
  if (max_pixels_per_frame_)
    ss << " max_pixels_per_frame=" << max_pixels_per_frame_.value();
  if (target_pixels_per_frame_)
    ss << " target_pixels_per_frame=" << target_pixels_per_frame_.value();
  ss << " }";
  return ss.Release();
}

const std::optional<size_t>& VideoSourceRestrictions::max_pixels_per_frame()
    const {
  return max_pixels_per_frame_;
}

const std::optional<size_t>& VideoSourceRestrictions::target_pixels_per_frame()
    const {
  return target_pixels_per_frame_;
}

const std::optional<double>& VideoSourceRestrictions::max_frame_rate() const {
  return max_frame_rate_;
}

void VideoSourceRestrictions::set_max_pixels_per_frame(
    std::optional<size_t> max_pixels_per_frame) {
  max_pixels_per_frame_ = std::move(max_pixels_per_frame);
}

void VideoSourceRestrictions::set_target_pixels_per_frame(
    std::optional<size_t> target_pixels_per_frame) {
  target_pixels_per_frame_ = std::move(target_pixels_per_frame);
}

void VideoSourceRestrictions::set_max_frame_rate(
    std::optional<double> max_frame_rate) {
  max_frame_rate_ = std::move(max_frame_rate);
}

void VideoSourceRestrictions::UpdateMin(const VideoSourceRestrictions& other) {
  if (max_pixels_per_frame_.has_value()) {
    max_pixels_per_frame_ = std::min(*max_pixels_per_frame_,
                                     other.max_pixels_per_frame().value_or(
                                         std::numeric_limits<size_t>::max()));
  } else {
    max_pixels_per_frame_ = other.max_pixels_per_frame();
  }
  if (target_pixels_per_frame_.has_value()) {
    target_pixels_per_frame_ = std::min(
        *target_pixels_per_frame_, other.target_pixels_per_frame().value_or(
                                       std::numeric_limits<size_t>::max()));
  } else {
    target_pixels_per_frame_ = other.target_pixels_per_frame();
  }
  if (max_frame_rate_.has_value()) {
    max_frame_rate_ = std::min(
        *max_frame_rate_,
        other.max_frame_rate().value_or(std::numeric_limits<double>::max()));
  } else {
    max_frame_rate_ = other.max_frame_rate();
  }
}

bool DidRestrictionsIncrease(VideoSourceRestrictions before,
                             VideoSourceRestrictions after) {
  bool decreased_resolution = DidDecreaseResolution(before, after);
  bool decreased_framerate = DidDecreaseFrameRate(before, after);
  bool same_resolution =
      before.max_pixels_per_frame() == after.max_pixels_per_frame();
  bool same_framerate = before.max_frame_rate() == after.max_frame_rate();

  return (decreased_resolution && decreased_framerate) ||
         (decreased_resolution && same_framerate) ||
         (same_resolution && decreased_framerate);
}

bool DidRestrictionsDecrease(VideoSourceRestrictions before,
                             VideoSourceRestrictions after) {
  bool increased_resolution = DidIncreaseResolution(before, after);
  bool increased_framerate = DidIncreaseFrameRate(before, after);
  bool same_resolution =
      before.max_pixels_per_frame() == after.max_pixels_per_frame();
  bool same_framerate = before.max_frame_rate() == after.max_frame_rate();

  return (increased_resolution && increased_framerate) ||
         (increased_resolution && same_framerate) ||
         (same_resolution && increased_framerate);
}

bool DidIncreaseResolution(VideoSourceRestrictions restrictions_before,
                           VideoSourceRestrictions restrictions_after) {
  if (!restrictions_before.max_pixels_per_frame().has_value())
    return false;
  if (!restrictions_after.max_pixels_per_frame().has_value())
    return true;
  return restrictions_after.max_pixels_per_frame().value() >
         restrictions_before.max_pixels_per_frame().value();
}

bool DidDecreaseResolution(VideoSourceRestrictions restrictions_before,
                           VideoSourceRestrictions restrictions_after) {
  if (!restrictions_after.max_pixels_per_frame().has_value())
    return false;
  if (!restrictions_before.max_pixels_per_frame().has_value())
    return true;
  return restrictions_after.max_pixels_per_frame().value() <
         restrictions_before.max_pixels_per_frame().value();
}

bool DidIncreaseFrameRate(VideoSourceRestrictions restrictions_before,
                          VideoSourceRestrictions restrictions_after) {
  if (!restrictions_before.max_frame_rate().has_value())
    return false;
  if (!restrictions_after.max_frame_rate().has_value())
    return true;
  return restrictions_after.max_frame_rate().value() >
         restrictions_before.max_frame_rate().value();
}

bool DidDecreaseFrameRate(VideoSourceRestrictions restrictions_before,
                          VideoSourceRestrictions restrictions_after) {
  if (!restrictions_after.max_frame_rate().has_value())
    return false;
  if (!restrictions_before.max_frame_rate().has_value())
    return true;
  return restrictions_after.max_frame_rate().value() <
         restrictions_before.max_frame_rate().value();
}

}  // namespace webrtc
