/*
 *  Copyright 2009 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 P2P_BASE_FAKETRANSPORTCONTROLLER_H_
#define P2P_BASE_FAKETRANSPORTCONTROLLER_H_

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

#include "p2p/base/fakedtlstransport.h"
#include "p2p/base/fakeicetransport.h"
#include "p2p/base/transportcontroller.h"
#include "rtc_base/bind.h"
#include "rtc_base/sslfingerprint.h"
#include "rtc_base/thread.h"

namespace cricket {

// Fake TransportController class, which can be passed into a WebRtcSession
// object for test purposes. Can be connected to other FakeTransportControllers
// via Connect().
//
// This fake is unusual in that for the most part, it's implemented with the
// real TransportController code, but with fake TransportChannels underneath.
class FakeTransportController : public TransportController {
 public:
  FakeTransportController()
      : TransportController(rtc::Thread::Current(),
                            rtc::Thread::Current(),
                            nullptr,
                            /*redetermine_role_on_ice_restart=*/true,
                            rtc::CryptoOptions()) {}

  explicit FakeTransportController(bool redetermine_role_on_ice_restart)
      : TransportController(rtc::Thread::Current(),
                            rtc::Thread::Current(),
                            nullptr,
                            redetermine_role_on_ice_restart,
                            rtc::CryptoOptions()) {}

  explicit FakeTransportController(IceRole role)
      : TransportController(rtc::Thread::Current(),
                            rtc::Thread::Current(),
                            nullptr,
                            /*redetermine_role_on_ice_restart=*/true,
                            rtc::CryptoOptions()) {
    SetIceRole(role);
  }

  explicit FakeTransportController(rtc::Thread* network_thread)
      : TransportController(rtc::Thread::Current(),
                            network_thread,
                            nullptr,
                            /*redetermine_role_on_ice_restart=*/true,
                            rtc::CryptoOptions()) {}

  FakeTransportController(rtc::Thread* network_thread, IceRole role)
      : TransportController(rtc::Thread::Current(),
                            network_thread,
                            nullptr,
                            /*redetermine_role_on_ice_restart=*/true,
                            rtc::CryptoOptions()) {
    SetIceRole(role);
  }

  FakeDtlsTransport* GetFakeDtlsTransport_n(const std::string& transport_name,
                                            int component) {
    return static_cast<FakeDtlsTransport*>(
        get_channel_for_testing(transport_name, component));
  }

  // Simulate the exchange of transport descriptions, and the gathering and
  // exchange of ICE candidates.
  void Connect(FakeTransportController* dest) {
    for (const std::string& transport_name : transport_names_for_testing()) {
      std::unique_ptr<rtc::SSLFingerprint> local_fingerprint;
      std::unique_ptr<rtc::SSLFingerprint> remote_fingerprint;
      if (certificate_for_testing()) {
        local_fingerprint.reset(rtc::SSLFingerprint::CreateFromCertificate(
            certificate_for_testing()));
      }
      if (dest->certificate_for_testing()) {
        remote_fingerprint.reset(rtc::SSLFingerprint::CreateFromCertificate(
            dest->certificate_for_testing()));
      }
      TransportDescription local_desc(
          std::vector<std::string>(),
          rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH),
          rtc::CreateRandomString(cricket::ICE_PWD_LENGTH),
          cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE,
          local_fingerprint.get());
      TransportDescription remote_desc(
          std::vector<std::string>(),
          rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH),
          rtc::CreateRandomString(cricket::ICE_PWD_LENGTH),
          cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE,
          remote_fingerprint.get());
      std::string err;
      SetLocalTransportDescription(transport_name, local_desc,
                                   cricket::CA_OFFER, &err);
      dest->SetRemoteTransportDescription(transport_name, local_desc,
                                          cricket::CA_OFFER, &err);
      dest->SetLocalTransportDescription(transport_name, remote_desc,
                                         cricket::CA_ANSWER, &err);
      SetRemoteTransportDescription(transport_name, remote_desc,
                                    cricket::CA_ANSWER, &err);
    }
    MaybeStartGathering();
    dest->MaybeStartGathering();
    network_thread()->Invoke<void>(
        RTC_FROM_HERE,
        rtc::Bind(&FakeTransportController::SetChannelDestinations_n, this,
                  dest));
  }

  void DestroyRtcpTransport(const std::string& transport_name) {
    DestroyDtlsTransport_n(transport_name,
                           cricket::ICE_CANDIDATE_COMPONENT_RTCP);
  }

 protected:
  IceTransportInternal* CreateIceTransportChannel_n(
      const std::string& transport_name,
      int component) override {
    return new FakeIceTransport(transport_name, component);
  }

  DtlsTransportInternal* CreateDtlsTransportChannel_n(
      const std::string& transport_name,
      int component,
      IceTransportInternal* ice) override {
    return new FakeDtlsTransport(static_cast<FakeIceTransport*>(ice));
  }

 private:
  void SetChannelDestinations_n(FakeTransportController* dest) {
    for (DtlsTransportInternal* tc : channels_for_testing()) {
      FakeDtlsTransport* local = static_cast<FakeDtlsTransport*>(tc);
      FakeDtlsTransport* remote = dest->GetFakeDtlsTransport_n(
          local->transport_name(), local->component());
      if (remote) {
        bool asymmetric = false;
        local->SetDestination(remote, asymmetric);
      }
    }
  }
};

}  // namespace cricket

#endif  // P2P_BASE_FAKETRANSPORTCONTROLLER_H_
