/*
 *  Copyright (c) 2004 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 "media/base/media_engine.h"

#include <stddef.h>

#include <cstdint>
#include <string>
#include <utility>

#include "absl/algorithm/container.h"
#include "api/field_trials_view.h"
#include "api/video/video_bitrate_allocation.h"
#include "media/base/codec_comparators.h"
#include "rtc_base/checks.h"
#include "rtc_base/string_encode.h"

namespace cricket {
namespace {
bool SupportsMode(const cricket::Codec& codec,
                  std::optional<std::string> scalability_mode) {
  if (!scalability_mode.has_value()) {
    return true;
  }
  return absl::c_any_of(
      codec.scalability_modes, [&](webrtc::ScalabilityMode mode) {
        return ScalabilityModeToString(mode) == *scalability_mode;
      });
}

}  // namespace

RtpCapabilities::RtpCapabilities() = default;
RtpCapabilities::~RtpCapabilities() = default;

webrtc::RtpParameters CreateRtpParametersWithOneEncoding() {
  webrtc::RtpParameters parameters;
  webrtc::RtpEncodingParameters encoding;
  parameters.encodings.push_back(encoding);
  return parameters;
}

webrtc::RtpParameters CreateRtpParametersWithEncodings(StreamParams sp) {
  std::vector<uint32_t> primary_ssrcs;
  sp.GetPrimarySsrcs(&primary_ssrcs);
  size_t encoding_count = primary_ssrcs.size();

  std::vector<webrtc::RtpEncodingParameters> encodings(encoding_count);
  for (size_t i = 0; i < encodings.size(); ++i) {
    encodings[i].ssrc = primary_ssrcs[i];
  }

  const std::vector<RidDescription>& rids = sp.rids();
  RTC_DCHECK(rids.size() == 0 || rids.size() == encoding_count);
  for (size_t i = 0; i < rids.size(); ++i) {
    encodings[i].rid = rids[i].rid;
  }

  webrtc::RtpParameters parameters;
  parameters.encodings = encodings;
  parameters.rtcp.cname = sp.cname;
  return parameters;
}

std::vector<webrtc::RtpExtension> GetDefaultEnabledRtpHeaderExtensions(
    const RtpHeaderExtensionQueryInterface& query_interface) {
  std::vector<webrtc::RtpExtension> extensions;
  for (const auto& entry : query_interface.GetRtpHeaderExtensions()) {
    if (entry.direction != webrtc::RtpTransceiverDirection::kStopped)
      extensions.emplace_back(entry.uri, *entry.preferred_id);
  }
  return extensions;
}

webrtc::RTCError CheckScalabilityModeValues(
    const webrtc::RtpParameters& rtp_parameters,
    rtc::ArrayView<cricket::Codec> send_codecs,
    std::optional<cricket::Codec> send_codec) {
  using webrtc::RTCErrorType;

  if (send_codecs.empty()) {
    // This is an audio sender or an extra check in the stack where the codec
    // list is not available and we can't check the scalability_mode values.
    return webrtc::RTCError::OK();
  }

  for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
    if (rtp_parameters.encodings[i].codec) {
      bool codecFound = false;
      for (const cricket::Codec& codec : send_codecs) {
        if (IsSameRtpCodec(codec, *rtp_parameters.encodings[i].codec) &&
            SupportsMode(codec, rtp_parameters.encodings[i].scalability_mode)) {
          codecFound = true;
          send_codec = codec;
          break;
        }
      }
      if (!codecFound) {
        LOG_AND_RETURN_ERROR(
            RTCErrorType::INVALID_MODIFICATION,
            "Attempted to use an unsupported codec for layer " +
                std::to_string(i));
      }
    }
    if (rtp_parameters.encodings[i].scalability_mode) {
      if (!send_codec) {
        bool scalabilityModeFound = false;
        for (const cricket::Codec& codec : send_codecs) {
          for (const auto& scalability_mode : codec.scalability_modes) {
            if (ScalabilityModeToString(scalability_mode) ==
                *rtp_parameters.encodings[i].scalability_mode) {
              scalabilityModeFound = true;
              break;
            }
          }
          if (scalabilityModeFound)
            break;
        }

        if (!scalabilityModeFound) {
          LOG_AND_RETURN_ERROR(
              RTCErrorType::INVALID_MODIFICATION,
              "Attempted to set RtpParameters scalabilityMode "
              "to an unsupported value for the current codecs.");
        }
      } else {
        bool scalabilityModeFound = false;
        for (const auto& scalability_mode : send_codec->scalability_modes) {
          if (ScalabilityModeToString(scalability_mode) ==
              *rtp_parameters.encodings[i].scalability_mode) {
            scalabilityModeFound = true;
            break;
          }
        }
        if (!scalabilityModeFound) {
          LOG_AND_RETURN_ERROR(
              RTCErrorType::INVALID_MODIFICATION,
              "Attempted to set RtpParameters scalabilityMode "
              "to an unsupported value for the current codecs.");
        }
      }
    }
  }

  return webrtc::RTCError::OK();
}

webrtc::RTCError CheckRtpParametersValues(
    const webrtc::RtpParameters& rtp_parameters,
    rtc::ArrayView<cricket::Codec> send_codecs,
    std::optional<cricket::Codec> send_codec,
    const webrtc::FieldTrialsView& field_trials) {
  using webrtc::RTCErrorType;

  bool has_scale_resolution_down_to = false;
  for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
    if (rtp_parameters.encodings[i].bitrate_priority <= 0) {
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
                           "Attempted to set RtpParameters bitrate_priority to "
                           "an invalid number. bitrate_priority must be > 0.");
    }
    if (rtp_parameters.encodings[i].scale_resolution_down_by &&
        *rtp_parameters.encodings[i].scale_resolution_down_by < 1.0) {
      LOG_AND_RETURN_ERROR(
          RTCErrorType::INVALID_RANGE,
          "Attempted to set RtpParameters scale_resolution_down_by to an "
          "invalid value. scale_resolution_down_by must be >= 1.0");
    }
    if (rtp_parameters.encodings[i].max_framerate &&
        *rtp_parameters.encodings[i].max_framerate < 0.0) {
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
                           "Attempted to set RtpParameters max_framerate to an "
                           "invalid value. max_framerate must be >= 0.0");
    }
    if (rtp_parameters.encodings[i].min_bitrate_bps &&
        rtp_parameters.encodings[i].max_bitrate_bps) {
      if (*rtp_parameters.encodings[i].max_bitrate_bps <
          *rtp_parameters.encodings[i].min_bitrate_bps) {
        LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::INVALID_RANGE,
                             "Attempted to set RtpParameters min bitrate "
                             "larger than max bitrate.");
      }
    }
    if (rtp_parameters.encodings[i].num_temporal_layers) {
      if (*rtp_parameters.encodings[i].num_temporal_layers < 1 ||
          *rtp_parameters.encodings[i].num_temporal_layers >
              webrtc::kMaxTemporalStreams) {
        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
                             "Attempted to set RtpParameters "
                             "num_temporal_layers to an invalid number.");
      }
    }

    if (rtp_parameters.encodings[i].scale_resolution_down_to.has_value()) {
      has_scale_resolution_down_to = true;
      if (rtp_parameters.encodings[i].scale_resolution_down_to->width <= 0 ||
          rtp_parameters.encodings[i].scale_resolution_down_to->height <= 0) {
        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
                             "The resolution dimensions must be positive.");
      }
    }

    if (!field_trials.IsEnabled("WebRTC-MixedCodecSimulcast")) {
      if (i > 0 && rtp_parameters.encodings[i - 1].codec !=
                       rtp_parameters.encodings[i].codec) {
        LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                             "Attempted to use different codec values for "
                             "different encodings.");
      }
    }
  }

  if (has_scale_resolution_down_to &&
      absl::c_any_of(rtp_parameters.encodings,
                     [](const webrtc::RtpEncodingParameters& encoding) {
                       return encoding.active &&
                              !encoding.scale_resolution_down_to.has_value();
                     })) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
                         "If a resolution is specified on any encoding then "
                         "it must be specified on all encodings.");
  }

  return CheckScalabilityModeValues(rtp_parameters, send_codecs, send_codec);
}

webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
    const webrtc::RtpParameters& old_rtp_parameters,
    const webrtc::RtpParameters& rtp_parameters,
    const webrtc::FieldTrialsView& field_trials) {
  return CheckRtpParametersInvalidModificationAndValues(
      old_rtp_parameters, rtp_parameters, {}, std::nullopt, field_trials);
}

webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
    const webrtc::RtpParameters& old_rtp_parameters,
    const webrtc::RtpParameters& rtp_parameters,
    rtc::ArrayView<cricket::Codec> send_codecs,
    std::optional<cricket::Codec> send_codec,
    const webrtc::FieldTrialsView& field_trials) {
  using webrtc::RTCErrorType;
  if (rtp_parameters.encodings.size() != old_rtp_parameters.encodings.size()) {
    LOG_AND_RETURN_ERROR(
        RTCErrorType::INVALID_MODIFICATION,
        "Attempted to set RtpParameters with different encoding count");
  }
  if (rtp_parameters.rtcp != old_rtp_parameters.rtcp) {
    LOG_AND_RETURN_ERROR(
        RTCErrorType::INVALID_MODIFICATION,
        "Attempted to set RtpParameters with modified RTCP parameters");
  }
  if (rtp_parameters.header_extensions !=
      old_rtp_parameters.header_extensions) {
    LOG_AND_RETURN_ERROR(
        RTCErrorType::INVALID_MODIFICATION,
        "Attempted to set RtpParameters with modified header extensions");
  }
  if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
                     [](const webrtc::RtpEncodingParameters& encoding1,
                        const webrtc::RtpEncodingParameters& encoding2) {
                       return encoding1.rid == encoding2.rid;
                     })) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
                         "Attempted to change RID values in the encodings.");
  }
  if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
                     [](const webrtc::RtpEncodingParameters& encoding1,
                        const webrtc::RtpEncodingParameters& encoding2) {
                       return encoding1.ssrc == encoding2.ssrc;
                     })) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
                         "Attempted to set RtpParameters with modified SSRC");
  }

  return CheckRtpParametersValues(rtp_parameters, send_codecs, send_codec,
                                  field_trials);
}

CompositeMediaEngine::CompositeMediaEngine(
    std::unique_ptr<webrtc::FieldTrialsView> trials,
    std::unique_ptr<VoiceEngineInterface> audio_engine,
    std::unique_ptr<VideoEngineInterface> video_engine)
    : trials_(std::move(trials)),
      voice_engine_(std::move(audio_engine)),
      video_engine_(std::move(video_engine)) {}

CompositeMediaEngine::CompositeMediaEngine(
    std::unique_ptr<VoiceEngineInterface> audio_engine,
    std::unique_ptr<VideoEngineInterface> video_engine)
    : CompositeMediaEngine(nullptr,
                           std::move(audio_engine),
                           std::move(video_engine)) {}

CompositeMediaEngine::~CompositeMediaEngine() = default;

bool CompositeMediaEngine::Init() {
  voice().Init();
  return true;
}

VoiceEngineInterface& CompositeMediaEngine::voice() {
  return *voice_engine_.get();
}

VideoEngineInterface& CompositeMediaEngine::video() {
  return *video_engine_.get();
}

const VoiceEngineInterface& CompositeMediaEngine::voice() const {
  return *voice_engine_.get();
}

const VideoEngineInterface& CompositeMediaEngine::video() const {
  return *video_engine_.get();
}

}  // namespace cricket
