// 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/bind_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/task/post_task.h"
#include "base/time/time.h"
#include "jingle/glue/thread_wrapper.h"
#include "remoting/base/chromium_url_request.h"
#include "remoting/base/grpc_support/grpc_async_unary_request.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/proto/ftl/v1/ftl_services.grpc.pb.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_grpc_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::TimeDelta::FromSeconds(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() {
  jingle_glue::JingleThreadWrapper::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;
  bool is_service_account =
      test::TestOAuthTokenGetter::IsServiceAccount(user_email);
  auto factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithPin(
      is_service_account, 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()),
      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>(),
      std::make_unique<ChromiumUrlRequestFactory>(
          url_loader_factory_owner_->GetURLLoaderFactory()),
      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().jid();
    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
