// 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,
    fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner>
        view_owner_request,
    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_->Initialize(
      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_owner_request));

  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
