// Copyright 2016 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/user_controller_impl.h"

#include <memory>
#include <utility>

#include <lib/fidl/cpp/synchronous_interface_ptr.h>

#include "peridot/lib/common/async_holder.h"
#include "peridot/lib/common/names.h"
#include "peridot/lib/common/teardown.h"
#include "peridot/lib/fidl/array_to_string.h"

namespace modular {

UserControllerImpl::UserControllerImpl(
    fuchsia::sys::Launcher* const launcher,
    fuchsia::modular::AppConfig sessionmgr,
    fuchsia::modular::AppConfig session_shell,
    fuchsia::modular::AppConfig story_shell,
    fidl::InterfaceHandle<fuchsia::auth::TokenManager> ledger_token_manager,
    fidl::InterfaceHandle<fuchsia::auth::TokenManager> agent_token_manager,
    fuchsia::modular::auth::AccountPtr account, zx::eventpair view_token,
    fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> base_shell_services,
    fidl::InterfaceRequest<fuchsia::modular::UserController>
        user_controller_request,
    DoneCallback done)
    : user_context_binding_(this),
      user_controller_binding_(this, std::move(user_controller_request)),
      base_shell_services_(base_shell_services ? base_shell_services.Bind()
                                               : nullptr),
      done_(std::move(done)) {
  // 0. Generate the path to map '/data' for the sessionmgr we are starting.
  std::string data_origin;
  if (!account) {
    // Guest user.
    // Generate a random number to be used in this case.
    uint32_t random_number = 0;
    zx_cprng_draw(&random_number, sizeof random_number);
    data_origin = std::string("/data/modular/USER_GUEST_") +
                  std::to_string(random_number);
  } else {
    // Non-guest user.
    data_origin = std::string("/data/modular/USER_") + std::string(account->id);
  }

  FXL_LOG(INFO) << "SESSIONMGR DATA ORIGIN IS " << data_origin;

  // 1. Launch Sessionmgr in the current environment.
  sessionmgr_app_ = std::make_unique<AppClient<fuchsia::modular::Lifecycle>>(
      launcher, std::move(sessionmgr), data_origin);

  // 2. Initialize the Sessionmgr service.
  sessionmgr_app_->services().ConnectToService(sessionmgr_.NewRequest());
  sessionmgr_->Initialize2(
      std::move(account), std::move(session_shell), std::move(story_shell),
      std::move(ledger_token_manager), std::move(agent_token_manager),
      user_context_binding_.NewBinding(), std::move(view_token));

  sessionmgr_app_->SetAppErrorHandler([this] {
    FXL_LOG(ERROR) << "Sessionmgr seems to have crashed unexpectedly. "
                   << "Calling done_().";
    // This prevents us from receiving any further requests.
    user_controller_binding_.Unbind();
    user_context_binding_.Unbind();
    // Logout(), which expects a graceful shutdown of sessionmgr, does not
    // apply here because sessionmgr crashed. Just run |done_| directly.
    done_(this);
  });
}

// |fuchsia::modular::UserController|
void UserControllerImpl::Logout(LogoutCallback done) {
  FXL_LOG(INFO) << "fuchsia::modular::UserController::Logout()";
  logout_response_callbacks_.push_back(done);
  if (logout_response_callbacks_.size() > 1) {
    return;
  }

  // This should prevent us from receiving any further requests.
  user_controller_binding_.Unbind();
  user_context_binding_.Unbind();

  sessionmgr_app_->Teardown(kSessionmgrTimeout, [this] {
    for (const auto& done : logout_response_callbacks_) {
      done();
    }
    // We announce |OnLogout| only at point just before deleting ourselves,
    // so we can avoid any race conditions that may be triggered by |Shutdown|
    // (which in-turn will call this |Logout| since we have not completed yet).
    for (auto& watcher : user_watchers_.ptrs()) {
      (*watcher)->OnLogout();
    }
    done_(this);
  });
}

// |UserContext|
void UserControllerImpl::GetPresentation(
    fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> request) {
  if (base_shell_services_) {
    base_shell_services_->ConnectToService(kPresentationService,
                                           request.TakeChannel());
  }
}

FuturePtr<> UserControllerImpl::SwapSessionShell(
    fuchsia::modular::AppConfig session_shell_config) {
  auto future = Future<>::Create("SwapSessionShell");
  SwapSessionShell(std::move(session_shell_config), future->Completer());
  return future;
}

// |fuchsia::modular::UserController|
void UserControllerImpl::SwapSessionShell(
    fuchsia::modular::AppConfig session_shell_config,
    SwapSessionShellCallback callback) {
  sessionmgr_->SwapSessionShell(std::move(session_shell_config), callback);
}

// |fuchsia::modular::UserController|
void UserControllerImpl::Watch(
    fidl::InterfaceHandle<fuchsia::modular::UserWatcher> watcher) {
  user_watchers_.AddInterfacePtr(watcher.Bind());
}

// |UserContext|
// TODO(alhaad): Reconcile UserContext.Logout() and UserControllerImpl.Logout().
void UserControllerImpl::Logout() {
  FXL_LOG(INFO) << "UserContext::Logout()";
  Logout([] {});
}

}  // namespace modular
