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

#ifndef API_TEST_FAKE_MEDIA_TRANSPORT_H_
#define API_TEST_FAKE_MEDIA_TRANSPORT_H_

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

#include "absl/algorithm/container.h"
#include "absl/memory/memory.h"
#include "api/media_transport_interface.h"

namespace webrtc {

// TODO(sukhanov): For now fake media transport does nothing and is used only
// in jsepcontroller unittests. In the future we should implement fake media
// transport, which forwards frames to another fake media transport, so we
// could unit test audio / video integration.
class FakeMediaTransport : public MediaTransportInterface {
 public:
  explicit FakeMediaTransport(
      const MediaTransportSettings& settings,
      const absl::optional<std::string>& transport_offer = "",
      const absl::optional<std::string>& remote_transport_parameters = "")
      : settings_(settings),
        transport_offer_(transport_offer),
        remote_transport_parameters_(remote_transport_parameters) {}
  ~FakeMediaTransport() = default;

  RTCError SendAudioFrame(uint64_t channel_id,
                          MediaTransportEncodedAudioFrame frame) override {
    return RTCError::OK();
  }

  RTCError SendVideoFrame(
      uint64_t channel_id,
      const MediaTransportEncodedVideoFrame& frame) override {
    return RTCError::OK();
  }

  RTCError RequestKeyFrame(uint64_t channel_id) override {
    return RTCError::OK();
  }

  void SetReceiveAudioSink(MediaTransportAudioSinkInterface* sink) override {}
  void SetReceiveVideoSink(MediaTransportVideoSinkInterface* sink) override {}

  // Returns true if fake media transport was created as a caller.
  bool is_caller() const { return settings_.is_caller; }
  absl::optional<std::string> pre_shared_key() const {
    return settings_.pre_shared_key;
  }

  RTCError OpenChannel(int channel_id) override { return RTCError::OK(); }

  RTCError SendData(int channel_id,
                    const SendDataParams& params,
                    const rtc::CopyOnWriteBuffer& buffer) override {
    return RTCError::OK();
  }

  RTCError CloseChannel(int channel_id) override { return RTCError::OK(); }

  void SetDataSink(DataChannelSink* sink) override {}

  void SetMediaTransportStateCallback(
      MediaTransportStateCallback* callback) override {
    state_callback_ = callback;
  }

  void SetState(webrtc::MediaTransportState state) {
    if (state_callback_) {
      state_callback_->OnStateChanged(state);
    }
  }

  void AddTargetTransferRateObserver(
      webrtc::TargetTransferRateObserver* observer) override {
    RTC_CHECK(!absl::c_linear_search(target_rate_observers_, observer));
    target_rate_observers_.push_back(observer);
  }

  void RemoveTargetTransferRateObserver(
      webrtc::TargetTransferRateObserver* observer) override {
    auto it = absl::c_find(target_rate_observers_, observer);
    if (it != target_rate_observers_.end()) {
      target_rate_observers_.erase(it);
    }
  }

  void SetAllocatedBitrateLimits(
      const MediaTransportAllocatedBitrateLimits& limits) override {}

  void SetTargetBitrateLimits(const MediaTransportTargetRateConstraints&
                                  target_rate_constraints) override {
    target_rate_constraints_in_order_.push_back(target_rate_constraints);
  }

  const std::vector<MediaTransportTargetRateConstraints>&
  target_rate_constraints_in_order() {
    return target_rate_constraints_in_order_;
  }

  int target_rate_observers_size() { return target_rate_observers_.size(); }

  // Settings that were passed down to fake media transport.
  const MediaTransportSettings& settings() { return settings_; }

  absl::optional<std::string> GetTransportParametersOffer() const override {
    // At least right now, we intend to use GetTransportParametersOffer before
    // the transport is connected. This may change in the future.
    RTC_CHECK(!is_connected_);
    return transport_offer_;
  }

  const absl::optional<std::string>& remote_transport_parameters() {
    return remote_transport_parameters_;
  }

  void Connect(rtc::PacketTransportInternal* packet_transport) {
    RTC_CHECK(!is_connected_) << "::Connect was called twice";
    is_connected_ = true;
  }

  bool is_connected() { return is_connected_; }

 private:
  const MediaTransportSettings settings_;
  MediaTransportStateCallback* state_callback_ = nullptr;
  std::vector<webrtc::TargetTransferRateObserver*> target_rate_observers_;
  const absl::optional<std::string> transport_offer_;
  const absl::optional<std::string> remote_transport_parameters_;
  bool is_connected_ = false;
  std::vector<MediaTransportTargetRateConstraints>
      target_rate_constraints_in_order_;
};

// Fake media transport factory creates fake media transport.
class FakeMediaTransportFactory : public MediaTransportFactory {
 public:
  explicit FakeMediaTransportFactory(
      const absl::optional<std::string>& transport_offer = "")
      : transport_offer_(transport_offer) {}
  ~FakeMediaTransportFactory() = default;

  std::string GetTransportName() const override { return "fake"; }

  RTCErrorOr<std::unique_ptr<MediaTransportInterface>> CreateMediaTransport(
      rtc::PacketTransportInternal* packet_transport,
      rtc::Thread* network_thread,
      const MediaTransportSettings& settings) override {
    std::unique_ptr<MediaTransportInterface> media_transport =
        absl::make_unique<FakeMediaTransport>(settings, transport_offer_);
    media_transport->Connect(packet_transport);
    return std::move(media_transport);
  }

  RTCErrorOr<std::unique_ptr<MediaTransportInterface>> CreateMediaTransport(
      rtc::Thread* network_thread,
      const MediaTransportSettings& settings) override {
    std::unique_ptr<MediaTransportInterface> media_transport =
        absl::make_unique<FakeMediaTransport>(
            settings, transport_offer_, settings.remote_transport_parameters);
    return std::move(media_transport);
  }

 private:
  const absl::optional<std::string> transport_offer_;
};

}  // namespace webrtc

#endif  // API_TEST_FAKE_MEDIA_TRANSPORT_H_
