// 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.

#include "remoting/protocol/session_config.h"

#include <algorithm>
#include <vector>

#include "base/check.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"

namespace remoting {
namespace protocol {

namespace {

bool IsChannelConfigSupported(const std::list<ChannelConfig>& list,
                              const ChannelConfig& value) {
  return std::find(list.begin(), list.end(), value) != list.end();
}

bool SelectCommonChannelConfig(const std::list<ChannelConfig>& host_configs,
                               const std::list<ChannelConfig>& client_configs,
                               ChannelConfig* config) {
  // Usually each of these lists will contain just a few elements, so iterating
  // over all of them is not a problem.
  std::list<ChannelConfig>::const_iterator it;
  for (it = client_configs.begin(); it != client_configs.end(); ++it) {
    if (IsChannelConfigSupported(host_configs, *it)) {
      *config = *it;
      return true;
    }
  }
  return false;
}

void UpdateConfigListToPreferTransport(std::list<ChannelConfig>* configs,
                                       ChannelConfig::TransportType transport) {
  std::vector<ChannelConfig> sorted(configs->begin(), configs->end());
  std::stable_sort(sorted.begin(), sorted.end(),
                   [transport](const ChannelConfig& a, const ChannelConfig& b) {
                     // |a| must precede |b| if |a| uses preferred transport and
                     // |b| doesn't.
                     return a.transport == transport &&
                            b.transport != transport;
                   });
  configs->assign(sorted.begin(), sorted.end());
}

}  // namespace

const int kDefaultStreamVersion = 2;
const int kControlStreamVersion = 3;

ChannelConfig ChannelConfig::None() {
  return ChannelConfig();
}

ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec)
    : transport(transport),
      version(version),
      codec(codec) {
}

bool ChannelConfig::operator==(const ChannelConfig& b) const {
  // If the transport field is set to NONE then all other fields are irrelevant.
  if (transport == ChannelConfig::TRANSPORT_NONE)
    return transport == b.transport;
  return transport == b.transport && version == b.version && codec == b.codec;
}

// static
std::unique_ptr<SessionConfig> SessionConfig::SelectCommon(
    const CandidateSessionConfig* client_config,
    const CandidateSessionConfig* host_config) {
  // Use WebRTC if both host and client support it.
  if (client_config->webrtc_supported() && host_config->webrtc_supported())
    return base::WrapUnique(new SessionConfig(Protocol::WEBRTC));

  // Reject connection if ICE is not supported by either of the peers.
  if (!host_config->ice_supported() || !client_config->ice_supported())
    return nullptr;

  std::unique_ptr<SessionConfig> result(new SessionConfig(Protocol::ICE));

  // If neither host nor the client have VP9 experiment enabled then remove it
  // from the list of host video configs.
  std::list<ChannelConfig> host_video_configs = host_config->video_configs();
  if (!client_config->vp9_experiment_enabled() &&
      !host_config->vp9_experiment_enabled()) {
    host_video_configs.remove_if([](const ChannelConfig& config) {
      return config.codec == ChannelConfig::CODEC_VP9;
    });
  }

  // If neither host nor the client have H264 experiment enabled then remove it
  // from the list of host video configs.
  if (!client_config->h264_experiment_enabled() &&
      !host_config->h264_experiment_enabled()) {
    host_video_configs.remove_if([](const ChannelConfig& config) {
      return config.codec == ChannelConfig::CODEC_H264;
    });
  }

  if (!SelectCommonChannelConfig(host_config->control_configs(),
                                 client_config->control_configs(),
                                 &result->control_config_) ||
      !SelectCommonChannelConfig(host_config->event_configs(),
                                 client_config->event_configs(),
                                 &result->event_config_) ||
      !SelectCommonChannelConfig(host_video_configs,
                                 client_config->video_configs(),
                                 &result->video_config_) ||
      !SelectCommonChannelConfig(host_config->audio_configs(),
                                 client_config->audio_configs(),
                                 &result->audio_config_)) {
    return nullptr;
  }

  return result;
}

// static
std::unique_ptr<SessionConfig> SessionConfig::GetFinalConfig(
    const CandidateSessionConfig* candidate_config) {
  if (candidate_config->webrtc_supported()) {
    if (candidate_config->ice_supported()) {
      LOG(ERROR) << "Received candidate config is ambiguous.";
      return nullptr;
    }
    return base::WrapUnique(new SessionConfig(Protocol::WEBRTC));
  }

  if (!candidate_config->ice_supported())
    return nullptr;

  if (candidate_config->control_configs().size() != 1 ||
      candidate_config->event_configs().size() != 1 ||
      candidate_config->video_configs().size() != 1 ||
      candidate_config->audio_configs().size() != 1) {
    return nullptr;
  }

  std::unique_ptr<SessionConfig> result(new SessionConfig(Protocol::ICE));
  result->control_config_ = candidate_config->control_configs().front();
  result->event_config_ = candidate_config->event_configs().front();
  result->video_config_ = candidate_config->video_configs().front();
  result->audio_config_ = candidate_config->audio_configs().front();

  return result;
}

// static
std::unique_ptr<SessionConfig> SessionConfig::ForTest() {
  std::unique_ptr<SessionConfig> result(new SessionConfig(Protocol::ICE));
  result->control_config_ =
      ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, kControlStreamVersion,
                    ChannelConfig::CODEC_UNDEFINED);
  result->event_config_ =
      ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, kDefaultStreamVersion,
                    ChannelConfig::CODEC_UNDEFINED);
  result->video_config_ =
      ChannelConfig(ChannelConfig::TRANSPORT_STREAM, kDefaultStreamVersion,
                    ChannelConfig::CODEC_VP8);
  result->audio_config_ =
      ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, kDefaultStreamVersion,
                    ChannelConfig::CODEC_OPUS);
  return result;
}

std::unique_ptr<SessionConfig> SessionConfig::ForTestWithAudio() {
  std::unique_ptr<SessionConfig> result(ForTest());
  result->audio_config_ = ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
                                        kDefaultStreamVersion,
                                        ChannelConfig::CODEC_OPUS);
  return result;
}

std::unique_ptr<SessionConfig> SessionConfig::ForTestWithVerbatimVideo() {
  std::unique_ptr<SessionConfig> result = ForTest();
  result->video_config_ = ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
                                        kDefaultStreamVersion,
                                        ChannelConfig::CODEC_VERBATIM);
  return result;
}

std::unique_ptr<SessionConfig> SessionConfig::ForTestWithWebrtc() {
  return base::WrapUnique(new SessionConfig(Protocol::WEBRTC));
}

const ChannelConfig& SessionConfig::control_config() const {
  DCHECK(protocol_ == Protocol::ICE);
  return control_config_;
}
const ChannelConfig& SessionConfig::event_config() const {
  DCHECK(protocol_ == Protocol::ICE);
  return event_config_;
}
const ChannelConfig& SessionConfig::video_config() const {
  DCHECK(protocol_ == Protocol::ICE);
  return video_config_;
}
const ChannelConfig& SessionConfig::audio_config() const {
  DCHECK(protocol_ == Protocol::ICE);
  return audio_config_;
}

SessionConfig::SessionConfig(Protocol protocol) : protocol_(protocol) {}

CandidateSessionConfig::CandidateSessionConfig() = default;
CandidateSessionConfig::CandidateSessionConfig(
    const CandidateSessionConfig& config) = default;
CandidateSessionConfig::~CandidateSessionConfig() = default;

bool CandidateSessionConfig::IsSupported(const SessionConfig& config) const {
  switch (config.protocol()) {
    case SessionConfig::Protocol::ICE:
      return ice_supported() &&
             IsChannelConfigSupported(control_configs_,
                                      config.control_config()) &&
             IsChannelConfigSupported(event_configs_, config.event_config()) &&
             IsChannelConfigSupported(video_configs_, config.video_config()) &&
             IsChannelConfigSupported(audio_configs_, config.audio_config());

    case SessionConfig::Protocol::WEBRTC:
      return webrtc_supported();
  }

  NOTREACHED();
  return false;
}

std::unique_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const {
  return base::WrapUnique(new CandidateSessionConfig(*this));
}

// static
std::unique_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() {
  return base::WrapUnique(new CandidateSessionConfig());
}

// static
std::unique_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateFrom(
    const SessionConfig& config) {
  std::unique_ptr<CandidateSessionConfig> result = CreateEmpty();

  switch (config.protocol()) {
    case SessionConfig::Protocol::WEBRTC:
      result->set_webrtc_supported(true);
      result->set_ice_supported(false);
      break;

    case SessionConfig::Protocol::ICE:
      result->set_webrtc_supported(false);
      result->set_ice_supported(true);
      result->mutable_control_configs()->push_back(config.control_config());
      result->mutable_event_configs()->push_back(config.event_config());
      result->mutable_video_configs()->push_back(config.video_config());
      result->mutable_audio_configs()->push_back(config.audio_config());
      break;
  }

  return result;
}

// static
std::unique_ptr<CandidateSessionConfig>
CandidateSessionConfig::CreateDefault() {
  std::unique_ptr<CandidateSessionConfig> result = CreateEmpty();

  result->set_ice_supported(true);

  // Control channel.
  result->mutable_control_configs()->push_back(
      ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
                    kControlStreamVersion,
                    ChannelConfig::CODEC_UNDEFINED));

  // Event channel.
  result->mutable_event_configs()->push_back(
      ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
                    kDefaultStreamVersion,
                    ChannelConfig::CODEC_UNDEFINED));

  // Video channel.
  result->mutable_video_configs()->push_back(
      ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
                    kDefaultStreamVersion,
                    ChannelConfig::CODEC_VP9));
  result->mutable_video_configs()->push_back(
      ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
                    kDefaultStreamVersion,
                    ChannelConfig::CODEC_VP8));

  // Audio channel.
  result->mutable_audio_configs()->push_back(
      ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
                    kDefaultStreamVersion,
                    ChannelConfig::CODEC_OPUS));
  result->mutable_audio_configs()->push_back(ChannelConfig::None());

  return result;
}

void CandidateSessionConfig::DisableAudioChannel() {
  mutable_audio_configs()->clear();
  mutable_audio_configs()->push_back(ChannelConfig());
}

void CandidateSessionConfig::PreferTransport(
    ChannelConfig::TransportType transport) {
  UpdateConfigListToPreferTransport(&control_configs_, transport);
  UpdateConfigListToPreferTransport(&event_configs_, transport);
  UpdateConfigListToPreferTransport(&video_configs_, transport);
  UpdateConfigListToPreferTransport(&audio_configs_, transport);
}

}  // namespace protocol
}  // namespace remoting
