/*
 *  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 <limits>

#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 {
  rtc::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
