// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef REMOTING_PROTOCOL_SESSION_CONFIG_H_
#define REMOTING_PROTOCOL_SESSION_CONFIG_H_

#include <list>
#include <memory>
#include <string>


namespace remoting {
namespace protocol {

extern const int kDefaultStreamVersion;

// Struct for configuration parameters of a single channel.
// Some channels (like video) may have multiple underlying sockets that need
// to be configured simultaneously.
struct ChannelConfig {
  enum TransportType {
    TRANSPORT_STREAM,
    TRANSPORT_MUX_STREAM,
    TRANSPORT_DATAGRAM,
    TRANSPORT_NONE,
  };

  enum Codec {
    CODEC_UNDEFINED,  // Used for event and control channels.
    CODEC_VERBATIM,
    CODEC_ZIP,
    CODEC_VP8,
    CODEC_VP9,
    CODEC_H264,
    CODEC_OPUS,
    CODEC_SPEEX,
    CODEC_AV1,
  };

  // Creates a config with transport field set to TRANSPORT_NONE which indicates
  // that corresponding channel is disabled.
  static ChannelConfig None();

  // Default constructor. Equivalent to None().
  ChannelConfig() = default;

  // Creates a channel config with the specified parameters.
  ChannelConfig(TransportType transport, int version, Codec codec);

  // operator== is overloaded so that std::find() works with
  // std::list<ChannelConfig>.
  bool operator==(const ChannelConfig& b) const;

  TransportType transport = TRANSPORT_NONE;
  int version = 0;
  Codec codec = CODEC_UNDEFINED;
};

class CandidateSessionConfig;

// SessionConfig is used to represent negotiated session configuration. Note
// that it's useful mainly for the legacy protocol. When using the new
// WebRTC-based protocol the using_webrtc() flag is set to true and all other
// fields should be ignored.
class SessionConfig {
 public:
  enum class Protocol {
    // ICE-based protocol (aka Chromotocol).
    ICE,

    // WebRTC-based protocol.
    WEBRTC,
  };

  // Selects session configuration that is supported by both participants.
  // nullptr is returned if such configuration doesn't exist. When selecting
  // channel configuration priority is given to the configs listed first
  // in |client_config|.
  static std::unique_ptr<SessionConfig> SelectCommon(
      const CandidateSessionConfig* client_config,
      const CandidateSessionConfig* host_config);

  // Extracts final protocol configuration. Must be used for the description
  // received in the session-accept stanza. If the selection is ambiguous
  // (e.g. there is more than one configuration for one of the channels)
  // or undefined (e.g. no configurations for a channel) then nullptr is
  // returned.
  static std::unique_ptr<SessionConfig> GetFinalConfig(
      const CandidateSessionConfig* candidate_config);

  // Returns a suitable session configuration for use in tests.
  static std::unique_ptr<SessionConfig> ForTest();
  static std::unique_ptr<SessionConfig> ForTestWithAudio();
  static std::unique_ptr<SessionConfig> ForTestWithVerbatimVideo();
  static std::unique_ptr<SessionConfig> ForTestWithWebrtc();

  Protocol protocol() const { return protocol_; }

  // All fields below should be ignored when protocol() is set to WEBRTC.
  const ChannelConfig& control_config() const;
  const ChannelConfig& event_config() const;
  const ChannelConfig& video_config() const;
  const ChannelConfig& audio_config() const;

  bool is_audio_enabled() const {
    return audio_config_.transport != ChannelConfig::TRANSPORT_NONE;
  }

 private:
  SessionConfig(Protocol protocol);

  const Protocol protocol_;

  ChannelConfig control_config_;
  ChannelConfig event_config_;
  ChannelConfig video_config_;
  ChannelConfig audio_config_;
};

// Defines session description that is sent from client to the host in the
// session-initiate message. It is different from the regular Config
// because it allows one to specify multiple configurations for each channel.
class CandidateSessionConfig {
 public:
  static std::unique_ptr<CandidateSessionConfig> CreateEmpty();
  static std::unique_ptr<CandidateSessionConfig> CreateFrom(
      const SessionConfig& config);
  static std::unique_ptr<CandidateSessionConfig> CreateDefault();

  ~CandidateSessionConfig();

  bool webrtc_supported() const { return webrtc_supported_; }
  void set_webrtc_supported(bool webrtc_supported) {
    webrtc_supported_ = webrtc_supported;
  }

  bool ice_supported() const { return ice_supported_; }
  void set_ice_supported(bool ice_supported) { ice_supported_ = ice_supported; }

  const std::list<ChannelConfig>& control_configs() const {
    return control_configs_;
  }

  std::list<ChannelConfig>* mutable_control_configs() {
    return &control_configs_;
  }

  const std::list<ChannelConfig>& event_configs() const {
    return event_configs_;
  }

  std::list<ChannelConfig>* mutable_event_configs() {
    return &event_configs_;
  }

  const std::list<ChannelConfig>& video_configs() const {
    return video_configs_;
  }

  std::list<ChannelConfig>* mutable_video_configs() {
    return &video_configs_;
  }

  const std::list<ChannelConfig>& audio_configs() const {
    return audio_configs_;
  }

  std::list<ChannelConfig>* mutable_audio_configs() {
    return &audio_configs_;
  }

  // Returns true if |config| is supported.
  bool IsSupported(const SessionConfig& config) const;

  std::unique_ptr<CandidateSessionConfig> Clone() const;

  // Helpers for enabling/disabling specific features.
  void DisableAudioChannel();
  void PreferTransport(ChannelConfig::TransportType transport);

 private:
  CandidateSessionConfig();
  explicit CandidateSessionConfig(const CandidateSessionConfig& config);
  CandidateSessionConfig& operator=(const CandidateSessionConfig& b);

  bool webrtc_supported_ = false;
  bool ice_supported_ = false;

  std::list<ChannelConfig> control_configs_;
  std::list<ChannelConfig> event_configs_;
  std::list<ChannelConfig> video_configs_;
  std::list<ChannelConfig> audio_configs_;
};

}  // namespace protocol
}  // namespace remoting

#endif  // REMOTING_PROTOCOL_SESSION_CONFIG_H_
