// 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 <lib/fit/function.h>
#include <zircon/status.h>

#include <utility>

#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_provider#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([](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) {
  Login2(fuchsia::modular::UserLoginParams2{
      .account_id = std::move(params.account_id),
  });
}

void SessionUserProviderImpl::Login2(fuchsia::modular::UserLoginParams2 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(), [](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(),
        [](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(),
        [](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
