// Copyright 2019 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/test/ftl_signaling_playground.h"

#include <inttypes.h>

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

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/guid.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "components/webrtc/thread_wrapper.h"
#include "remoting/base/logging.h"
#include "remoting/base/oauth_token_getter_impl.h"
#include "remoting/base/oauth_token_getter_proxy.h"
#include "remoting/base/rsa_key_pair.h"
#include "remoting/base/service_urls.h"
#include "remoting/base/url_request_context_getter.h"
#include "remoting/protocol/auth_util.h"
#include "remoting/protocol/chromium_port_allocator_factory.h"
#include "remoting/protocol/jingle_session_manager.h"
#include "remoting/protocol/me2me_host_authenticator_factory.h"
#include "remoting/protocol/negotiating_client_authenticator.h"
#include "remoting/protocol/network_settings.h"
#include "remoting/protocol/pairing_registry.h"
#include "remoting/protocol/transport.h"
#include "remoting/protocol/transport_context.h"
#include "remoting/signaling/ftl_signal_strategy.h"
#include "remoting/test/cli_util.h"
#include "remoting/test/test_device_id_provider.h"
#include "remoting/test/test_oauth_token_getter.h"
#include "remoting/test/test_token_storage.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/transitional_url_loader_factory_owner.h"

namespace remoting {

namespace {

constexpr char kSwitchNameHelp[] = "help";
constexpr char kSwitchNameUsername[] = "username";
constexpr char kSwitchNameHostOwner[] = "host-owner";
constexpr char kSwitchNameStoragePath[] = "storage-path";
constexpr char kSwitchNamePin[] = "pin";
constexpr char kSwitchNameHostId[] = "host-id";
constexpr char kSwitchNameUseChromotocol[] = "use-chromotocol";

// Delay to allow sending session-terminate before tearing down.
constexpr base::TimeDelta kTearDownDelay = base::Seconds(2);

const char* SignalStrategyErrorToString(SignalStrategy::Error error) {
  switch (error) {
    case SignalStrategy::OK:
      return "OK";
    case SignalStrategy::AUTHENTICATION_FAILED:
      return "AUTHENTICATION_FAILED";
    case SignalStrategy::NETWORK_ERROR:
      return "NETWORK_ERROR";
    case SignalStrategy::PROTOCOL_ERROR:
      return "PROTOCOL_ERROR";
  }
  return "";
}

}  // namespace

FtlSignalingPlayground::FtlSignalingPlayground() = default;

FtlSignalingPlayground::~FtlSignalingPlayground() = default;

bool FtlSignalingPlayground::ShouldPrintHelp() {
  return base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchNameHelp);
}

void FtlSignalingPlayground::PrintHelp() {
  printf(
      "Usage: %s [--auth-code=<auth-code>] [--host-id=<host-id>] [--pin=<pin>] "
      "[--storage-path=<storage-path>] [--username=<example@gmail.com>] "
      "[--host-owner=<example@gmail.com>] [--use-chromotocol]\n",
      base::CommandLine::ForCurrentProcess()
          ->GetProgram()
          .MaybeAsASCII()
          .c_str());
}

void FtlSignalingPlayground::StartLoop() {
  webrtc::ThreadWrapper::EnsureForCurrentMessageLoop();

  base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
  std::string username = cmd_line->GetSwitchValueASCII(kSwitchNameUsername);
  base::FilePath storage_path =
      cmd_line->GetSwitchValuePath(kSwitchNameStoragePath);

  storage_ = test::TestTokenStorage::OnDisk(username, storage_path);
  token_getter_ = std::make_unique<test::TestOAuthTokenGetter>(storage_.get());

  auto url_request_context_getter =
      base::MakeRefCounted<URLRequestContextGetter>(
          base::ThreadTaskRunnerHandle::Get());
  url_loader_factory_owner_ =
      std::make_unique<network::TransitionalURLLoaderFactoryOwner>(
          url_request_context_getter);

  base::RunLoop initialize_token_getter_loop;
  token_getter_->Initialize(initialize_token_getter_loop.QuitClosure());
  initialize_token_getter_loop.Run();

  std::vector<test::CommandOption> options{
      {"AcceptIncoming",
       base::BindRepeating(&FtlSignalingPlayground::AcceptIncoming,
                           base::Unretained(this))},
      {"ConnectToHost",
       base::BindRepeating(&FtlSignalingPlayground::ConnectToHost,
                           base::Unretained(this))}};

  test::RunCommandOptionsLoop(options);
}

void FtlSignalingPlayground::AcceptIncoming(base::OnceClosure on_done) {
  current_callback_ = std::move(on_done);

  SetUpSignaling();

  std::string host_id;
  auto* cmd = base::CommandLine::ForCurrentProcess();
  if (cmd->HasSwitch(kSwitchNameHostId)) {
    host_id = cmd->GetSwitchValueASCII(kSwitchNameHostId);
  } else {
    host_id = base::GenerateGUID();
  }
  HOST_LOG << "Using host ID: " << host_id;

  std::string pin =
      test::ReadStringFromCommandLineOrStdin(kSwitchNamePin, "Pin: ");

  std::string pin_hash = protocol::GetSharedSecretHash(host_id, pin);

  auto key_pair = RsaKeyPair::Generate();
  std::string cert = key_pair->GenerateCertificate();

  std::string user_email = storage_->FetchUserEmail();
  std::string host_owner = cmd->HasSwitch(kSwitchNameHostOwner)
                               ? cmd->GetSwitchValueASCII(kSwitchNameHostOwner)
                               : user_email;
  HOST_LOG << "Using host owner: " << host_owner;
  auto factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithPin(
      host_owner, cert, key_pair,
      /* domain_list */ {}, pin_hash, /* pairing_registry */ {});
  session_manager_->set_authenticator_factory(std::move(factory));
  HOST_LOG << "Waiting for incoming session...";
  session_manager_->AcceptIncoming(base::BindRepeating(
      &FtlSignalingPlayground::OnIncomingSession, base::Unretained(this)));
}

void FtlSignalingPlayground::OnIncomingSession(
    protocol::Session* owned_session,
    protocol::SessionManager::IncomingSessionResponse* response) {
  HOST_LOG << "Received incoming session!\n";
  RegisterSession(base::WrapUnique(owned_session),
                  protocol::TransportRole::SERVER);
  *response = protocol::SessionManager::ACCEPT;
}

void FtlSignalingPlayground::ConnectToHost(base::OnceClosure on_done) {
  current_callback_ = std::move(on_done);
  on_signaling_connected_callback_ =
      base::BindOnce(&FtlSignalingPlayground::OnClientSignalingConnected,
                     base::Unretained(this));
  SetUpSignaling();
}

void FtlSignalingPlayground::OnClientSignalingConnected() {
  std::string host_id =
      test::ReadStringFromCommandLineOrStdin(kSwitchNameHostId, "Host ID: ");
  printf("Host JID: ");
  std::string host_jid = test::ReadString();

  protocol::ClientAuthenticationConfig client_auth_config;
  client_auth_config.host_id = host_id;
  client_auth_config.fetch_secret_callback = base::BindRepeating(
      &FtlSignalingPlayground::FetchSecret, base::Unretained(this));

  auto session = session_manager_->Connect(
      SignalingAddress(host_jid),
      std::make_unique<protocol::NegotiatingClientAuthenticator>(
          signal_strategy_->GetLocalAddress().id(), host_jid,
          client_auth_config));
  RegisterSession(std::move(session), protocol::TransportRole::CLIENT);
}

void FtlSignalingPlayground::FetchSecret(
    bool pairing_supported,
    const protocol::SecretFetchedCallback& secret_fetched_callback) {
  std::string pin =
      test::ReadStringFromCommandLineOrStdin(kSwitchNamePin, "Pin: ");
  HOST_LOG << "Using PIN: " << pin;
  secret_fetched_callback.Run(pin);
}

void FtlSignalingPlayground::SetUpSignaling() {
  signal_strategy_ = std::make_unique<FtlSignalStrategy>(
      std::make_unique<OAuthTokenGetterProxy>(token_getter_->GetWeakPtr()),
      url_loader_factory_owner_->GetURLLoaderFactory(),
      std::make_unique<test::TestDeviceIdProvider>(storage_.get()));
  signal_strategy_->AddListener(this);

  session_manager_ =
      std::make_unique<protocol::JingleSessionManager>(signal_strategy_.get());
  auto protocol_config = protocol::CandidateSessionConfig::CreateDefault();
  bool use_chromotocol = base::CommandLine::ForCurrentProcess()->HasSwitch(
      kSwitchNameUseChromotocol);
  protocol_config->set_webrtc_supported(!use_chromotocol);
  session_manager_->set_protocol_config(std::move(protocol_config));

  signal_strategy_->Connect();
}

void FtlSignalingPlayground::TearDownSignaling() {
  on_signaling_connected_callback_.Reset();
  session_.reset();
  webrtc_connection_.reset();
  ice_connection_.reset();
  signal_strategy_->RemoveListener(this);
  session_manager_.reset();
  signal_strategy_.reset();
}

void FtlSignalingPlayground::RegisterSession(
    std::unique_ptr<protocol::Session> session,
    protocol::TransportRole transport_role) {
  session_ = std::move(session);
  transport_role_ = transport_role;
  std::unique_ptr<protocol::SessionManager> session_manager(
      new protocol::JingleSessionManager(signal_strategy_.get()));
  session_->SetEventHandler(this);
}

void FtlSignalingPlayground::InitializeTransport() {
  protocol::NetworkSettings network_settings(
      protocol::NetworkSettings::NAT_TRAVERSAL_FULL);
  auto transport_context = base::MakeRefCounted<protocol::TransportContext>(
      std::make_unique<protocol::ChromiumPortAllocatorFactory>(),
      url_loader_factory_owner_->GetURLLoaderFactory(), nullptr,
      network_settings, transport_role_);
  auto close_callback =
      base::BindOnce(&FtlSignalingPlayground::AsyncTearDownAndRunCallback,
                     base::Unretained(this));
  if (session_->config().protocol() ==
      protocol::SessionConfig::Protocol::WEBRTC) {
    webrtc_connection_ = std::make_unique<test::FakeWebrtcConnection>(
        transport_context, std::move(close_callback));
    session_->SetTransport(webrtc_connection_->transport());
  } else {
    ice_connection_ = std::make_unique<test::FakeIceConnection>(
        transport_context, std::move(close_callback));
    session_->SetTransport(ice_connection_->transport());
  }
}

void FtlSignalingPlayground::OnSignalStrategyStateChange(
    SignalStrategy::State state) {
  if (state == SignalStrategy::CONNECTING) {
    HOST_LOG << "Connecting";
    return;
  }

  if (state == SignalStrategy::CONNECTED) {
    HOST_LOG << "Signaling connected. New JID: "
             << signal_strategy_->GetLocalAddress().id();
    if (on_signaling_connected_callback_) {
      std::move(on_signaling_connected_callback_).Run();
    }
    return;
  }

  DCHECK(state == SignalStrategy::DISCONNECTED);

  auto error = signal_strategy_->GetError();

  TearDownSignaling();

  HOST_LOG << "Signaling disconnected. error="
           << SignalStrategyErrorToString(error);

  if (error == SignalStrategy::AUTHENTICATION_FAILED) {
    if (current_callback_) {
      token_getter_->ResetWithAuthenticationFlow(std::move(current_callback_));
    } else {
      token_getter_->InvalidateCache();
    }
    return;
  }

  if (current_callback_) {
    std::move(current_callback_).Run();
  }
}

bool FtlSignalingPlayground::OnSignalStrategyIncomingStanza(
    const jingle_xmpp::XmlElement* stanza) {
  return false;
}

void FtlSignalingPlayground::OnSessionStateChange(
    protocol::Session::State state) {
  HOST_LOG << "New session state: " << state;
  switch (state) {
    case protocol::Session::INITIALIZING:
    case protocol::Session::CONNECTING:
    case protocol::Session::ACCEPTING:
    case protocol::Session::AUTHENTICATING:
      // Don't care about these events.
      return;
    case protocol::Session::ACCEPTED:
      InitializeTransport();
      return;
    case protocol::Session::AUTHENTICATED:
      HOST_LOG << "Session is successfully authenticated!!!";
      if (ice_connection_) {
        ice_connection_->OnAuthenticated();
      }
      return;

    case protocol::Session::CLOSED:
    case protocol::Session::FAILED:
      LOG(ERROR) << "Session failed/closed. Error: " << session_->error();
      break;
  }

  AsyncTearDownAndRunCallback();
}

void FtlSignalingPlayground::AsyncTearDownAndRunCallback() {
  HOST_LOG << "Tearing down in " << kTearDownDelay;
  tear_down_timer_.Start(FROM_HERE, kTearDownDelay, this,
                         &FtlSignalingPlayground::TearDownAndRunCallback);
}

void FtlSignalingPlayground::TearDownAndRunCallback() {
  TearDownSignaling();
  if (current_callback_) {
    std::move(current_callback_).Run();
  }
}

}  // namespace remoting
