// Copyright 2019 The Fuchsia 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 "peridot/bin/basemgr/session_user_provider_impl.h"

#include <utility>

#include <lib/fit/function.h>
#include <zircon/status.h>

#include "peridot/lib/fidl/clone.h"
#include "peridot/lib/fidl/json_xdr.h"

namespace modular {

namespace {

// Url of the application launching token manager
constexpr char kSessionUserProviderAppUrl[] = "session_user_provider_url";

// Dev auth provider configuration
constexpr char kDevAuthProviderType[] = "dev";
constexpr char kDevAuthProviderUrl[] =
    "fuchsia-pkg://fuchsia.com/dev_auth_providers#meta/"
    "dev_auth_provider.cmx";

// Google auth provider configuration
constexpr char kGoogleAuthProviderType[] = "google";
constexpr char kGoogleAuthProviderUrl[] =
    "fuchsia-pkg://fuchsia.com/google_auth_provider#meta/"
    "google_auth_provider.cmx";

std::string GetRandomId() {
  uint32_t random_number = 0;
  zx_cprng_draw(&random_number, sizeof random_number);
  return std::to_string(random_number);
}

// Returns the corresponding |auth_provider_type| string that maps to
// |fuchsia::modular::auth::IdentityProvider| value.
// TODO(ukode): Convert enum |fuchsia::modular::auth::IdentityProvider| to
// fidl::String datatype to make it consistent in the future.
std::string MapIdentityProviderToAuthProviderType(
    const fuchsia::modular::auth::IdentityProvider idp) {
  switch (idp) {
    case fuchsia::modular::auth::IdentityProvider::DEV:
      return kDevAuthProviderType;
    case fuchsia::modular::auth::IdentityProvider::GOOGLE:
      return kGoogleAuthProviderType;
  }
  FXL_DCHECK(false) << "Unrecognized IDP.";
}

// Returns a list of supported auth provider configurations that includes the
// type, startup parameters and the url of the auth provider component.
// TODO(ukode): This list will be derived from a config package in the future.
std::vector<fuchsia::auth::AuthProviderConfig> GetAuthProviderConfigs() {
  fuchsia::auth::AuthProviderConfig dev_auth_provider_config;
  dev_auth_provider_config.auth_provider_type = kDevAuthProviderType;
  dev_auth_provider_config.url = kDevAuthProviderUrl;

  fuchsia::auth::AuthProviderConfig google_auth_provider_config;
  google_auth_provider_config.auth_provider_type = kGoogleAuthProviderType;
  google_auth_provider_config.url = kGoogleAuthProviderUrl;

  std::vector<fuchsia::auth::AuthProviderConfig> auth_provider_configs;
  auth_provider_configs.push_back(std::move(google_auth_provider_config));
  auth_provider_configs.push_back(std::move(dev_auth_provider_config));

  return auth_provider_configs;
}

}  // namespace

SessionUserProviderImpl::SessionUserProviderImpl(
    fuchsia::auth::account::AccountManager* const account_manager,
    fuchsia::auth::TokenManagerFactory* const token_manager_factory,
    fuchsia::auth::AuthenticationContextProviderPtr
        authentication_context_provider,
    OnInitializeCallback on_initialize, OnLoginCallback on_login)
    : account_manager_(account_manager),
      token_manager_factory_(token_manager_factory),
      authentication_context_provider_(
          std::move(authentication_context_provider)),
      authentication_context_provider_binding_(this),
      account_listener_binding_(this),
      on_initialize_(std::move(on_initialize)),
      on_login_(std::move(on_login)) {
  FXL_CHECK(account_manager_);
  FXL_CHECK(token_manager_factory_);
  FXL_CHECK(authentication_context_provider_);
  FXL_CHECK(on_initialize_);
  FXL_CHECK(on_login_);

  authentication_context_provider_binding_.set_error_handler(
      [this](zx_status_t status) {
        FXL_LOG(WARNING) << "AuthenticationContextProvider disconnected.";
        authentication_context_provider_binding_.Unbind();
      });

  // Register SessionUserProvider as an AccountListener. All added accounts will
  // be logged in to a session.
  account_listener_binding_.set_error_handler([this](zx_status_t status) {
    FXL_LOG(FATAL) << "AccountListener disconnected with status: "
                   << zx_status_get_string(status);
  });

  fuchsia::auth::account::AccountListenerOptions options;
  options.initial_state = true;
  options.add_account = true;
  account_manager_->RegisterAccountListener(
      account_listener_binding_.NewBinding(), std::move(options),
      [](fuchsia::auth::account::Status status) {
        if (status == fuchsia::auth::account::Status::OK) {
          FXL_LOG(INFO) << "AccountListener registered.";
        } else {
          FXL_LOG(FATAL) << "AccountListener registration failed with status: "
                         << (uint32_t)status;
        }
      });
}

void SessionUserProviderImpl::Connect(
    fidl::InterfaceRequest<fuchsia::modular::UserProvider> request) {
  bindings_.AddBinding(this, std::move(request));
}

void SessionUserProviderImpl::AddUser(
    fuchsia::modular::auth::IdentityProvider identity_provider,
    AddUserCallback callback) {
  account_manager_->ProvisionFromAuthProvider(
      authentication_context_provider_binding_.NewBinding(),
      MapIdentityProviderToAuthProviderType(identity_provider),
      [callback = std::move(callback)](
          fuchsia::auth::account::Status status,
          std::unique_ptr<fuchsia::auth::account::LocalAccountId>
              account_id) mutable {
        if (status != fuchsia::auth::account::Status::OK || !account_id) {
          FXL_LOG(ERROR) << "Failed to provision new account from wuth "
                            "provider with status: "
                         << (uint32_t)status;
          callback(nullptr,
                   "Failed to provision new account from auth provider.");
          return;
        }

        // To interface with BaseShells that haven't migrated to use
        // AccountManager, we give them the string account_id to call back
        // Login with.
        auto account = fuchsia::modular::auth::Account::New();
        account->id = std::to_string(account_id->id);

        callback(std::move(account), "");
      });
}

void SessionUserProviderImpl::Login(fuchsia::modular::UserLoginParams params) {
  bool login_as_guest = params.account_id.is_null() || params.account_id == "";
  if (login_as_guest) {
    FXL_LOG(INFO) << "fuchsia::modular::UserProvider::Login() Login as guest";
    // If requested, login as guest  by creating token managers with token
    // manager factory.
    auto account_id = GetRandomId();

    // Instead of passing token_manager_factory all the way to agents and
    // runners with all auth provider configurations, send two
    // |fuchsia::auth::TokenManager| handles, one for ledger and one for
    // agents for the given user account |account_id|.
    fuchsia::auth::TokenManagerPtr ledger_token_manager =
        CreateTokenManager(account_id);
    fuchsia::auth::TokenManagerPtr agent_token_manager =
        CreateTokenManager(account_id);

    on_login_(/* account= */ nullptr, std::move(ledger_token_manager),
              std::move(agent_token_manager));
  } else {
    FXL_LOG(INFO) << "fuchsia::modular::UserProvider::Login() Login as "
                     "authenticated user";
    fuchsia::auth::account::LocalAccountId account_id;
    account_id.id = std::atoll(params.account_id->c_str());

    fuchsia::auth::account::AccountPtr account;
    account_manager_->GetAccount(
        account_id, authentication_context_provider_binding_.NewBinding(),
        account.NewRequest(), [this](fuchsia::auth::account::Status status) {
          FXL_LOG(INFO) << "Got account with status: " << (uint32_t)status;
        });

    fuchsia::auth::account::PersonaPtr persona;
    account->GetDefaultPersona(
        persona.NewRequest(),
        [](fuchsia::auth::account::Status status,
           std::unique_ptr<fuchsia::auth::account::LocalPersonaId>) {
          FXL_LOG(INFO) << "Got default persona with status: "
                        << (uint32_t)status;
        });

    fuchsia::auth::TokenManagerPtr ledger_token_manager;
    persona->GetTokenManager(
        kSessionUserProviderAppUrl, ledger_token_manager.NewRequest(),
        [this](fuchsia::auth::account::Status status) {
          FXL_LOG(INFO) << "Got token manager with status: "
                        << (uint32_t)status;
        });

    fuchsia::auth::TokenManagerPtr agent_token_manager;
    persona->GetTokenManager(
        kSessionUserProviderAppUrl, agent_token_manager.NewRequest(),
        [this](fuchsia::auth::account::Status status) {
          FXL_LOG(INFO) << "Got token manager with status: "
                        << (uint32_t)status;
        });

    auto account_deprecated = fuchsia::modular::auth::Account::New();
    account_deprecated->id = params.account_id->c_str();

    // Save the newly added user as a joined persona.
    struct JoinedPersona joined_persona {
      .account = std::move(account), .persona = std::move(persona),
    };
    joined_personas_.emplace_back(std::move(joined_persona));

    on_login_(std::move(account_deprecated), std::move(ledger_token_manager),
              std::move(agent_token_manager));
  }
}

void SessionUserProviderImpl::RemoveAllUsers(fit::function<void()> callback) {
  joined_personas_.clear();
  account_manager_->GetAccountIds(
      [this, callback = std::move(callback)](
          std::vector<fuchsia::auth::account::LocalAccountId>
              account_ids) mutable {
        if (account_ids.empty()) {
          callback();
          return;
        }

        // We only expect there to be one account at most.
        account_manager_->RemoveAccount(
            account_ids.at(0),
            [callback = std::move(callback)](fuchsia::auth::account::Status) {
              callback();
            });
      });
}

void SessionUserProviderImpl::RemoveUser(std::string account_id,
                                         RemoveUserCallback callback) {
  FXL_LOG(INFO) << "RemoveUser() is not implemented yet.";
  callback("");
}

void SessionUserProviderImpl::PreviousUsers(PreviousUsersCallback callback) {
  FXL_LOG(INFO) << "PreviousUsers() is not implemented yet";
  fidl::VectorPtr<::fuchsia::modular::auth::Account> users;
  callback(std::move(users));
}

void SessionUserProviderImpl::GetAuthenticationUIContext(
    fidl::InterfaceRequest<fuchsia::auth::AuthenticationUIContext> request) {
  authentication_context_provider_->GetAuthenticationUIContext(
      std::move(request));
}

fuchsia::auth::TokenManagerPtr SessionUserProviderImpl::CreateTokenManager(
    std::string account_id) {
  FXL_CHECK(token_manager_factory_);

  fuchsia::auth::TokenManagerPtr token_mgr;
  token_manager_factory_->GetTokenManager(
      account_id, kSessionUserProviderAppUrl, GetAuthProviderConfigs(),
      authentication_context_provider_binding_.NewBinding(),
      token_mgr.NewRequest());

  token_mgr.set_error_handler([account_id](zx_status_t status) {
    FXL_LOG(INFO) << "Token Manager for account:" << account_id
                  << " disconnected";
  });

  return token_mgr;
}

void SessionUserProviderImpl::OnInitialize(
    std::vector<fuchsia::auth::account::AccountAuthState>,
    OnInitializeCallback callback) {
  callback();
  on_initialize_();
}

void SessionUserProviderImpl::OnAccountAdded(
    fuchsia::auth::account::LocalAccountId account_id,
    OnAccountAddedCallback callback) {
  // TODO(MF-311): Get rid of this once clients of UserProvider interface start
  // using AccountManager.
  fuchsia::modular::UserLoginParams params;
  params.account_id = std::to_string(account_id.id);
  // Base shell may also call Login with the newly added account, but the Login
  // flow should be resilient to multiple invocations.
  Login(std::move(params));
  callback();
}

void SessionUserProviderImpl::OnAccountRemoved(
    fuchsia::auth::account::LocalAccountId, OnAccountRemovedCallback callback) {
  callback();
}

void SessionUserProviderImpl::OnAuthStateChanged(
    fuchsia::auth::account::AccountAuthState,
    OnAuthStateChangedCallback callback) {
  callback();
}

}  // namespace modular
