/*
 *  Copyright 2012 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.
 */

// This file contains declarations of interfaces that wrap SDP-related
// constructs; session descriptions and ICE candidates. The inner "webrtc::"
// objects shouldn't be accessed directly; the intention is that an application
// using the PeerConnection API only creates these objects from strings, and
// them passes them into the PeerConnection.
//
// Though in the future, we're planning to provide an SDP parsing API, with a
// structure more friendly than webrtc::SessionDescription.

#ifndef API_JSEP_H_
#define API_JSEP_H_

#include <stddef.h>

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/nullability.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "api/candidate.h"
#include "api/ref_count.h"
#include "api/rtc_error.h"
#include "api/sequence_checker.h"
#include "rtc_base/system/no_unique_address.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/thread_annotations.h"

namespace webrtc {

class SessionDescription;

struct SdpParseError {
 public:
  // The sdp line that causes the error.
  std::string line;
  // Explains the error.
  std::string description;
};

// Class representation of an ICE candidate.
class RTC_EXPORT IceCandidate final {
 public:
  IceCandidate(absl::string_view sdp_mid,
               int sdp_mline_index,
               const Candidate& candidate);
  ~IceCandidate() = default;

  IceCandidate(const IceCandidate&) = delete;
  IceCandidate& operator=(const IceCandidate&) = delete;

  // Parses an sdp candidate string (only the first line) to construct an
  // IceCandidate instance. If an error occurs, details about the error can
  // optionally be returned via the `error` paramter, and the function returns
  // nullptr.
  static std::unique_ptr<IceCandidate> Create(
      absl::string_view mid,
      int sdp_mline_index,
      absl::string_view sdp,
      SdpParseError* absl_nullable error = nullptr);

  // If present, this is the value of the "a=mid" attribute of the candidate's
  // m= section in SDP, which identifies the m= section.
  // TODO: webrtc:406795492 - string_view.
  std::string sdp_mid() const { return sdp_mid_; }

  // This indicates the index (starting at zero) of m= section this candidate
  // is associated with. Needed when an endpoint doesn't support MIDs.
  int sdp_mline_index() const { return sdp_mline_index_; }

  // Only for use internally.
  const Candidate& candidate() const { return candidate_; }

  // The URL of the ICE server which this candidate was gathered from.
  // TODO: webrtc:406795492 - string_view.
  std::string server_url() const { return candidate_.url(); }

  // Creates a SDP-ized form of this candidate.
  std::string ToString() const;

  // TODO: webrtc:406795492 - Deprecate and remove this method.
  bool ToString(std::string* out) const {
    if (!out)
      return false;
    *out = ToString();
    return !out->empty();
  }

  template <typename Sink>
  friend void AbslStringify(Sink& sink, const IceCandidate& c) {
    absl::Format(&sink, "IceCandidate: {'%s', %i, '%s'}", c.sdp_mid_.c_str(),
                 c.sdp_mline_index_, c.ToString().c_str());
  }

 private:
  const std::string sdp_mid_;
  const int sdp_mline_index_;
  const Candidate candidate_;
};

// TODO: webrtc:406795492 - Deprecate and eventually remove these types when no
// longer referenced. They're provided here for backwards compatiblity.
using JsepIceCandidate = IceCandidate;
using IceCandidateInterface = IceCandidate;

// Creates an IceCandidate based on SDP string.
// Returns null if the sdp string can't be parsed.
// `error` may be null.
RTC_EXPORT IceCandidate* CreateIceCandidate(absl::string_view sdp_mid,
                                            int sdp_mline_index,
                                            const std::string& sdp,
                                            SdpParseError* error);

// Creates an IceCandidate based on a parsed candidate structure.
RTC_EXPORT std::unique_ptr<IceCandidate> CreateIceCandidate(
    absl::string_view sdp_mid,
    int sdp_mline_index,
    const Candidate& candidate);

// This class represents a collection of candidates for a specific m= section.
// Used in SessionDescriptionInterface.
class IceCandidateCollection final {
 public:
  IceCandidateCollection() = default;
  explicit IceCandidateCollection(
      std::vector<std::unique_ptr<IceCandidate>>&& candidates)
      : candidates_(std::move(candidates)) {}
  ~IceCandidateCollection() = default;

  // Move constructor is defined so that a vector of IceCandidateCollections
  // can be resized.
  IceCandidateCollection(IceCandidateCollection&& o) = default;

  IceCandidateCollection(const IceCandidateCollection&) = delete;
  IceCandidateCollection& operator=(const IceCandidateCollection&) = delete;

  size_t count() const {
    RTC_DCHECK_RUN_ON(&sequence_checker_);
    return candidates_.size();
  }
  bool empty() const {
    RTC_DCHECK_RUN_ON(&sequence_checker_);
    return candidates_.empty();
  }
  const IceCandidate* at(size_t index) const;

  // Adds and takes ownership of the IceCandidate.
  void add(std::unique_ptr<IceCandidate> candidate);
  [[deprecated("Use unique_ptr version")]]
  void add(IceCandidate* candidate);

  // Appends a collection of candidates.
  void Append(IceCandidateCollection collection);

  // Removes the candidate that has a matching address and protocol.
  //
  // Returns the number of candidates that were removed.
  size_t remove(const IceCandidate* candidate);

  const std::vector<std::unique_ptr<IceCandidate>>& candidates() const {
    return candidates_;
  }

  // Returns true if an equivalent `candidate` exist in the collection.
  bool HasCandidate(const IceCandidate* candidate) const;

  IceCandidateCollection Clone() const;
  void RelinquishThreadOwnership();

 private:
  RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_;
  std::vector<std::unique_ptr<IceCandidate>> candidates_
      RTC_GUARDED_BY(sequence_checker_);
};

// Enum that describes the type of the SessionDescriptionInterface.
// Corresponds to RTCSdpType in the WebRTC specification.
// https://w3c.github.io/webrtc-pc/#dom-rtcsdptype
enum class SdpType {
  kOffer,     // Description must be treated as an SDP offer.
  kPrAnswer,  // Description must be treated as an SDP answer, but not a final
              // answer.
  kAnswer,    // Description must be treated as an SDP final answer, and the
              // offer-answer exchange must be considered complete after
              // receiving this.
  kRollback   // Resets any pending offers and sets signaling state back to
              // stable.
};

// Returns the string form of the given SDP type. String forms are defined in
// SessionDescriptionInterface.
RTC_EXPORT const char* SdpTypeToString(SdpType type);

template <typename Sink>
void AbslStringify(Sink& sink, SdpType sdp_type) {
  sink.Append(SdpTypeToString(sdp_type));
}

// Returns the SdpType from its string form. The string form can be one of the
// constants defined in SessionDescriptionInterface. Passing in any other string
// results in nullopt.
RTC_EXPORT std::optional<SdpType> SdpTypeFromString(
    const std::string& type_str);

// Class representation of an SDP session description.
//
// An instance of this interface is supposed to be owned by one class at a time
// and is therefore not expected to be thread safe.
//
// An instance can be created by CreateSessionDescription.
struct EncodingOptions {
  bool use_wildcard = false;
};

class RTC_EXPORT SessionDescriptionInterface final {
 public:
  static std::unique_ptr<SessionDescriptionInterface> Create(
      SdpType type,
      std::unique_ptr<SessionDescription> description,
      absl::string_view id,
      absl::string_view version,
      std::vector<IceCandidateCollection> candidates = {},
      EncodingOptions encoding_options = {});

  SessionDescriptionInterface(const SessionDescriptionInterface&) = delete;
  SessionDescriptionInterface& operator=(const SessionDescriptionInterface&) =
      delete;

  // String representations of the supported SDP types.
  static const char kOffer[];
  static const char kPrAnswer[];
  static const char kAnswer[];
  static const char kRollback[];

  ~SessionDescriptionInterface();

  // Create a new SessionDescriptionInterface object
  // with the same values as the old object.
  std::unique_ptr<SessionDescriptionInterface> Clone() const;

  absl::string_view id() const { return id_; }
  absl::string_view version() const { return version_; }

  // Only for use internally.
  const SessionDescription* description() const { return description_.get(); }
  SessionDescription* description() { return description_.get(); }

  // Get the session id and session version, which are defined based on
  // RFC 4566 for the SDP o= line.
  std::string session_id() const { return std::string(id()); }
  std::string session_version() const { return std::string(version()); }

  // Returns the type of this session description as an SdpType. Descriptions of
  // the various types are found in the SdpType documentation.
  SdpType GetType() const { return sdp_type_; }

  // TODO(steveanton): Remove this in favor of `GetType` that returns SdpType.
  std::string type() const { return SdpTypeToString(sdp_type_); }

  // Adds the specified candidate to the description.
  //
  // Ownership is not transferred.
  //
  // Returns false if the session description does not have a media section
  // that corresponds to `candidate.sdp_mid()` or
  // `candidate.sdp_mline_index()`.
  bool AddCandidate(const IceCandidate* candidate);

  // Removes the first matching candidate (at most 1) from the description
  // that meets the `Candidate::MatchesForRemoval()` requirement and matches
  // either the `IceCandidate::sdp_mid()` property or
  // `IceCandidate::sdp_mline_index()`.
  //
  // Returns false if no matching candidate was found (and removed).
  bool RemoveCandidate(const IceCandidate* candidate);

  // Returns the number of m= sections in the session description.
  size_t number_of_mediasections() const;

  // Returns a collection of all candidates that belong to a certain m=
  // section.
  const IceCandidateCollection* candidates(size_t mediasection_index) const;

  EncodingOptions encoding_options() const {
    RTC_DCHECK_RUN_ON(&sequence_checker_);
    return encoding_options_;
  }

  // Serializes the description to SDP.
  bool ToString(std::string* out) const {
    if (!out)
      return false;
    *out = ToString();
    return !out->empty();
  }

  // Serializes the description to SDP.
  std::string ToString() const;

  template <typename Sink>
  friend void AbslStringify(Sink& sink, const SessionDescriptionInterface& p) {
    sink.Append("\n--- BEGIN SDP ");
    absl::Format(&sink, "%v", p.GetType());
    sink.Append(" ---\n");
    std::string temp = p.ToString();
    if (!temp.empty()) {
      sink.Append(temp);
    } else {
      sink.Append("<no session description>\n");
    }
    sink.Append("--- END SDP ---\n");
  }

  // Resets the internal sequence_checker_ to not be attached to a particular
  // thread. Used when transfering object ownership between threads. Must be
  // called by the thread that currently owns the object before transferring the
  // ownership.
  void RelinquishThreadOwnership();

 protected:
  explicit SessionDescriptionInterface(
      SdpType type,
      std::unique_ptr<SessionDescription> description,
      absl::string_view id,
      absl::string_view version,
      std::vector<IceCandidateCollection> candidates = {},
      EncodingOptions encoding_options = {});

 private:
  bool IsValidMLineIndex(int index) const;
  bool GetMediasectionIndex(const IceCandidate* candidate, size_t* index) const;
  int GetMediasectionIndex(absl::string_view mid) const;

  const SdpType sdp_type_;
  const std::string id_;
  const std::string version_;
  absl_nullable const std::unique_ptr<SessionDescription> description_;

  RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_{
      SequenceChecker::kDetached};
  std::vector<IceCandidateCollection> candidate_collection_
      RTC_GUARDED_BY(sequence_checker_);
  const EncodingOptions encoding_options_ RTC_GUARDED_BY(sequence_checker_);
};

// Creates a SessionDescriptionInterface based on the SDP string and the type.
// Returns null if the SDP string cannot be parsed.
// If using the signature with `error_out`, details of the parsing error may be
// written to `error_out` if it is not null.
RTC_EXPORT std::unique_ptr<SessionDescriptionInterface>
CreateSessionDescription(SdpType type, absl::string_view sdp);
RTC_EXPORT std::unique_ptr<SessionDescriptionInterface>
CreateSessionDescription(SdpType type,
                         absl::string_view sdp,
                         SdpParseError* error_out);

// Creates a SessionDescriptionInterface based on a parsed SDP structure and the
// given type, ID and version.
std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
    SdpType type,
    absl::string_view session_id,
    absl::string_view session_version,
    std::unique_ptr<SessionDescription> description);

// Creates a rollback session description object (SdpType::kRollback).
std::unique_ptr<SessionDescriptionInterface> CreateRollbackSessionDescription(
    absl::string_view session_id = "",
    absl::string_view session_version = "");

// CreateOffer and CreateAnswer callback interface.
class RTC_EXPORT CreateSessionDescriptionObserver : public RefCountInterface {
 public:
  // This callback transfers the ownership of the `desc`.
  // TODO(deadbeef): Make this take an std::unique_ptr<> to avoid confusion
  // around ownership.
  virtual void OnSuccess(SessionDescriptionInterface* desc) = 0;
  // The OnFailure callback takes an RTCError, which consists of an
  // error code and a string.
  // RTCError is non-copyable, so it must be passed using std::move.
  // Earlier versions of the API used a string argument. This version
  // is removed; its functionality was the same as passing
  // error.message.
  virtual void OnFailure(RTCError error) = 0;

 protected:
  ~CreateSessionDescriptionObserver() override = default;
};

// SetLocalDescription and SetRemoteDescription callback interface.
class RTC_EXPORT SetSessionDescriptionObserver : public RefCountInterface {
 public:
  virtual void OnSuccess() = 0;
  // See description in CreateSessionDescriptionObserver for OnFailure.
  virtual void OnFailure(RTCError error) = 0;

 protected:
  ~SetSessionDescriptionObserver() override = default;
};

}  // namespace webrtc

#endif  // API_JSEP_H_
