// Copyright 2017 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 "src/modular/bin/sessionmgr/sessionmgr_impl.h"

#include <fuchsia/element/cpp/fidl.h>
#include <fuchsia/session/cpp/fidl.h>
#include <fuchsia/ui/app/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <lib/zx/eventpair.h>
#include <zircon/status.h>

#include <memory>

#include <fbl/unique_fd.h>

#include "src/lib/files/directory.h"
#include "src/lib/fsl/io/fd.h"
#include "src/lib/fsl/types/type_converters.h"
#include "src/modular/bin/basemgr/cobalt/cobalt.h"
#include "src/modular/bin/sessionmgr/puppet_master/make_production_impl.h"
#include "src/modular/bin/sessionmgr/story_runner/story_controller_impl.h"
#include "src/modular/lib/common/teardown.h"
#include "src/modular/lib/fidl/array_to_string.h"
#include "src/modular/lib/fidl/clone.h"
#include "src/modular/lib/fidl/json_xdr.h"

namespace modular {

using cobalt_registry::ModularLifetimeEventsMetricDimensionEventType;

namespace {

constexpr char kSessionEnvironmentLabelPrefix[] = "session-";

// The name in the outgoing debug directory (hub) for developer session control
// services.
constexpr char kSessionCtlDir[] = "sessionctl";

// Creates a function that can be used as termination action passed to OnTerminate(),
// which when called invokes the reset() method on the object pointed to by the
// argument. Used to reset() fidl pointers and std::unique_ptr<>s fields.
template <typename X>
fit::function<void(fit::function<void()>)> Reset(std::unique_ptr<X>* const field) {
  return [field](fit::function<void()> cont) {
    field->reset();
    cont();
  };
}

template <typename X>
fit::function<void(fit::function<void()>)> Reset(fidl::InterfacePtr<X>* const field) {
  return [field](fit::function<void()> cont) {
    field->Unbind();
    cont();
  };
}

// Creates a function that can be used as termination action passed to OnTerminate(),
// which when called asynchronously invokes the Teardown() method on the object
// pointed to by the argument. Used to teardown AppClient and AsyncHolder
// members.
template <typename X>
fit::function<void(fit::function<void()>)> Teardown(const zx::duration timeout,
                                                    const char* const message, X* const field) {
  return [timeout, message, field](fit::function<void()> cont) {
    field->Teardown(timeout, [message, cont = std::move(cont)] {
      if (message) {
        FX_DLOGS(INFO) << "- " << message << " down.";
      }
      cont();
    });
  };
}

}  // namespace

SessionmgrImpl::SessionmgrImpl(sys::ComponentContext* const component_context,
                               modular::ModularConfigAccessor config_accessor,
                               inspect::Node node_object)
    : sessionmgr_context_(component_context),
      config_accessor_(std::move(config_accessor)),
      inspect_root_node_(std::move(node_object)),
      story_provider_impl_("StoryProviderImpl"),
      agent_runner_("AgentRunner"),
      weak_ptr_factory_(this) {
  sessionmgr_context_->outgoing()->AddPublicService<fuchsia::modular::internal::Sessionmgr>(
      [this](fidl::InterfaceRequest<fuchsia::modular::internal::Sessionmgr> request) {
        bindings_.AddBinding(this, std::move(request));
      });
}

SessionmgrImpl::~SessionmgrImpl() = default;

// Initialize is called for each new session, denoted by a unique session_id. In other words, it
// initializes a session, not a SessionmgrImpl (despite the class-scoped name). (Ironically, the
// |finitish_initialization_| lambda does initialize some Sessionmgr-scoped resources only once,
// upon demand.)
void SessionmgrImpl::Initialize(
    std::string session_id,
    fidl::InterfaceHandle<fuchsia::modular::internal::SessionContext> session_context,
    fuchsia::sys::ServiceList additional_services_for_agents,
    fuchsia::ui::views::ViewToken view_token, fuchsia::ui::views::ViewRefControl control_ref,
    fuchsia::ui::views::ViewRef view_ref) {
  FX_LOGS(INFO) << "SessionmgrImpl::Initialize() called.";

  session_context_ = session_context.Bind();
  OnTerminate(Reset(&session_context_));

  session_storage_ = std::make_unique<SessionStorage>();
  OnTerminate(Reset(&session_storage_));

  InitializeSessionEnvironment(session_id);

  // Create |puppet_master_| before |agent_runner_| to ensure agents can use it when terminating.
  InitializePuppetMaster();
  InitializeElementManager();

  InitializeStartupAgentLauncher(std::move(additional_services_for_agents));
  InitializeAgentRunner(config_accessor_.session_shell_app_config().url());
  InitializeStartupAgents();

  scenic::ViewRefPair view_ref_pair =
      scenic::ViewRefPair{.control_ref = {std::move(control_ref.reference)},
                          .view_ref = {std::move(view_ref.reference)}};

  InitializeSessionShell(CloneStruct(config_accessor_.session_shell_app_config()),
                         std::move(view_token), std::move(view_ref_pair));

  // We create |story_provider_impl_| after |agent_runner_| so
  // story_provider_impl_ is terminated before agent_runner_, which will cause
  // all modules to be terminated before agents are terminated. Agents must
  // outlive the stories which contain modules that are connected to those
  // agents.
  InitializeStoryProvider(CloneStruct(config_accessor_.story_shell_app_config()),
                          config_accessor_.use_session_shell_for_story_shell_factory());
  ConnectSessionShellToStoryProvider();

  InitializeSessionCtl();

  ReportEvent(ModularLifetimeEventsMetricDimensionEventType::BootedToSessionMgr);
}

void SessionmgrImpl::ConnectSessionShellToStoryProvider() {
  // If connecting to the SessionShell errors out, use the GraphicalPresenter
  ui_handlers_.session_shell.set_error_handler(
      [weak_this = weak_ptr_factory_.GetWeakPtr()](zx_status_t status) mutable {
        if (!weak_this) {
          return;
        }
        FX_PLOGS(INFO, status) << "Failed to connect to SessionShell, using GraphicalPresenter";
        if (weak_this->story_provider_impl_.get() && weak_this->ui_handlers_.graphical_presenter) {
          weak_this->story_provider_impl_.get()->SetPresentationProtocol(
              PresentationProtocolPtr{std::move(weak_this->ui_handlers_.graphical_presenter)});
        }
      });

  // If connecting to the GraphicalPresenter errors out, use the SessionShell
  ui_handlers_.graphical_presenter.set_error_handler(
      [weak_this = weak_ptr_factory_.GetWeakPtr()](zx_status_t status) mutable {
        if (!weak_this) {
          return;
        }
        FX_PLOGS(INFO, status) << "Failed to connect to GraphicalPresenter, using SessionShell";
        if (weak_this->story_provider_impl_.get() && weak_this->ui_handlers_.session_shell) {
          weak_this->story_provider_impl_.get()->SetPresentationProtocol(
              PresentationProtocolPtr{std::move(weak_this->ui_handlers_.session_shell)});
        }
      });

  ConnectToSessionShellService(ui_handlers_.session_shell.NewRequest());
  ConnectToSessionShellService(ui_handlers_.graphical_presenter.NewRequest());
}

// Create an environment in which to launch story shells and mods. Note that agents cannot be
// launched from this environment because the environment hosts its data directories in a
// session-specific subdirectory of data, and certain agents in existing test devices expect the
// data at a hardcoded, top-level /data directory.
//
// True separation among multiple sessions is currently NOT supported for many reasons, so as
// a temporary workaround, agents are started in the /sys realm via a different launcher.
//
// Future implementations will use the new SessionFramework, which will provide support for
// multiple sessions.
void SessionmgrImpl::InitializeSessionEnvironment(std::string session_id) {
  session_id_ = session_id;

  // Create the session's environment (in which we run stories, modules, agents, and so on) as a
  // child of sessionmgr's environment. Add session-provided additional services, |kEnvServices|.
  static const auto* const kEnvServices =
      new std::vector<std::string>{fuchsia::intl::PropertyProvider::Name_};

  session_environment_ = std::make_unique<Environment>(
      /* parent_env = */ sessionmgr_context_->svc()->Connect<fuchsia::sys::Environment>(),
      std::string(kSessionEnvironmentLabelPrefix) + session_id_, *kEnvServices,
      /* kill_on_oom = */ true);

  // Get the default launcher from the new |session_environment_| to wrap in an
  // |ArgvInjectingLauncher|
  fuchsia::sys::LauncherPtr session_environment_launcher;
  session_environment_->environment()->GetLauncher(session_environment_launcher.NewRequest());

  // Wrap the launcher and override it with the new |ArgvInjectingLauncher|
  ArgvInjectingLauncher::ArgvMap argv_map;
  for (auto& component : config_accessor_.sessionmgr_config().component_args()) {
    argv_map.insert(std::make_pair(component.url(), component.args()));
  }
  session_environment_->OverrideLauncher(
      std::make_unique<ArgvInjectingLauncher>(std::move(session_environment_launcher), argv_map));

  // Add session-provided services.
  session_environment_->AddService<fuchsia::intl::PropertyProvider>(
      [this](fidl::InterfaceRequest<fuchsia::intl::PropertyProvider> request) {
        if (terminating_) {
          request.Close(ZX_ERR_UNAVAILABLE);
          return;
        }
        sessionmgr_context_->svc()->Connect<fuchsia::intl::PropertyProvider>(std::move(request));
      });

  OnTerminate(Reset(&session_environment_));
}

void SessionmgrImpl::InitializeStartupAgentLauncher(
    fuchsia::sys::ServiceList additional_services_for_agents) {
  FX_DCHECK(puppet_master_impl_);

  startup_agent_launcher_ = std::make_unique<StartupAgentLauncher>(
      &config_accessor_,
      [this](fidl::InterfaceRequest<fuchsia::modular::PuppetMaster> request) {
        puppet_master_impl_->Connect(std::move(request));
      },
      [this](fidl::InterfaceRequest<fuchsia::modular::SessionRestartController> request) {
        if (terminating_) {
          request.Close(ZX_ERR_UNAVAILABLE);
          return;
        }
        session_restart_controller_bindings_.AddBinding(this, std::move(request));
      },
      [this](fidl::InterfaceRequest<fuchsia::intl::PropertyProvider> request) {
        if (terminating_) {
          request.Close(ZX_ERR_UNAVAILABLE);
          return;
        }
        sessionmgr_context_->svc()->Connect<fuchsia::intl::PropertyProvider>(std::move(request));
      },
      [this](fidl::InterfaceRequest<fuchsia::element::Manager> request) {
        if (terminating_) {
          request.Close(ZX_ERR_UNAVAILABLE);
          return;
        }
        element_manager_impl_->Connect(std::move(request));
      },
      std::move(additional_services_for_agents), [this]() { return terminating_; });
  OnTerminate(Reset(&startup_agent_launcher_));
}

void SessionmgrImpl::InitializeAgentRunner(std::string session_shell_url) {
  FX_DCHECK(startup_agent_launcher_);

  // Initialize the AgentRunner.
  //
  // The AgentRunner must use its own |ArgvInjectingLauncher|, different from the
  // |ArgvInjectingLauncher| launcher used for mods: The AgentRunner's launcher must come from the
  // sys realm (the realm that sessionmgr is running in) due to devices in the field which rely on
  // agents /data path mappings being consistent. There is no current solution for the migration of
  // /data when a component topology changes. This will be resolved in Session Framework, which
  // will soon deprecated and replace this Modular solution.
  //
  // Create a new launcher that uses sessionmgr's realm launcher.
  std::map<std::string, std::string> agent_service_index;
  for (auto& entry : config_accessor_.sessionmgr_config().agent_service_index()) {
    agent_service_index.emplace(entry.service_name(), entry.agent_url());
  }

  ArgvInjectingLauncher::ArgvMap argv_map;
  for (auto& component : config_accessor_.sessionmgr_config().component_args()) {
    argv_map.insert(std::make_pair(component.url(), component.args()));
  }

  fuchsia::sys::LauncherPtr launcher;
  session_environment_->environment()->GetLauncher(launcher.NewRequest());
  agent_runner_launcher_ = std::make_unique<ArgvInjectingLauncher>(std::move(launcher), argv_map);

  auto restart_session_on_agent_crash =
      config_accessor_.sessionmgr_config().restart_session_on_agent_crash();
  restart_session_on_agent_crash.push_back(session_shell_url);

  agent_runner_.reset(new AgentRunner(
      &config_accessor_, agent_runner_launcher_.get(), startup_agent_launcher_.get(),
      &inspect_root_node_,
      /*on_critical_agent_crash=*/[this] { RestartDueToCriticalFailure(); },
      std::move(agent_service_index), config_accessor_.sessionmgr_config().session_agents(),
      restart_session_on_agent_crash, sessionmgr_context_));
  OnTerminate(Teardown(kAgentRunnerTimeout, "AgentRunner", &agent_runner_));
}

void SessionmgrImpl::InitializeStartupAgents() {
  FX_DCHECK(startup_agent_launcher_);
  FX_DCHECK(agent_runner_.get());

  startup_agent_launcher_->StartAgents(agent_runner_.get(),
                                       config_accessor_.sessionmgr_config().session_agents(),
                                       config_accessor_.sessionmgr_config().startup_agents());
}

void SessionmgrImpl::InitializeStoryProvider(
    fuchsia::modular::session::AppConfig story_shell_config,
    bool use_session_shell_for_story_shell_factory) {
  FX_DCHECK(agent_runner_.get());
  FX_DCHECK(session_environment_);
  FX_DCHECK(session_storage_);
  FX_DCHECK(startup_agent_launcher_);

  // The StoryShellFactory to use when creating story shells, or nullptr if no
  // such factory exists.
  fidl::InterfacePtr<fuchsia::modular::StoryShellFactory> story_shell_factory_ptr;

  if (use_session_shell_for_story_shell_factory) {
    ConnectToSessionShellService(story_shell_factory_ptr.NewRequest());
  }

  ComponentContextInfo component_context_info{
      agent_runner_.get(), config_accessor_.sessionmgr_config().session_agents()};
  story_provider_impl_.reset(new StoryProviderImpl(
      session_environment_.get(), session_storage_.get(), std::move(story_shell_config),
      std::move(story_shell_factory_ptr), component_context_info, startup_agent_launcher_.get(),
      &inspect_root_node_));
  OnTerminate(Teardown(kStoryProviderTimeout, "StoryProvider", &story_provider_impl_));
}

void SessionmgrImpl::InitializePuppetMaster() {
  FX_DCHECK(session_storage_);

  story_command_executor_ = MakeProductionStoryCommandExecutor(session_storage_.get());
  OnTerminate(Reset(&story_command_executor_));

  puppet_master_impl_ =
      std::make_unique<PuppetMasterImpl>(session_storage_.get(), story_command_executor_.get());
  OnTerminate(Reset(&puppet_master_impl_));
}

void SessionmgrImpl::InitializeElementManager() {
  FX_DCHECK(session_storage_);

  element_manager_impl_ = std::make_unique<ElementManagerImpl>(session_storage_.get());
  OnTerminate(Reset(&element_manager_impl_));
}

void SessionmgrImpl::InitializeSessionCtl() {
  FX_DCHECK(puppet_master_impl_);

  session_ctl_ = std::make_unique<SessionCtl>(sessionmgr_context_->outgoing()->debug_dir(),
                                              kSessionCtlDir, puppet_master_impl_.get());
  OnTerminate(Reset(&session_ctl_));
}

void SessionmgrImpl::InitializeSessionShell(
    fuchsia::modular::session::AppConfig session_shell_config,
    fuchsia::ui::views::ViewToken view_token, scenic::ViewRefPair view_ref_pair) {
  session_shell_url_ = session_shell_config.url();

  // We setup our own view and make the fuchsia::modular::SessionShell a child
  // of it.
  auto scenic = sessionmgr_context_->svc()->Connect<fuchsia::ui::scenic::Scenic>();

  scenic::ViewContext view_context = {
      .session_and_listener_request =
          scenic::CreateScenicSessionPtrAndListenerRequest(scenic.get()),
      .view_token = std::move(view_token),
      .view_ref_pair = std::move(view_ref_pair),
      .component_context = sessionmgr_context_,
  };
  session_shell_view_host_ = std::make_unique<ViewHost>(std::move(view_context));

  RunSessionShell(std::move(session_shell_config));
}

void SessionmgrImpl::RunSessionShell(fuchsia::modular::session::AppConfig session_shell_config) {
  FX_DCHECK(session_environment_);
  FX_DCHECK(agent_runner_.get());
  FX_DCHECK(puppet_master_impl_);
  FX_DCHECK(session_shell_view_host_);

  ComponentContextInfo component_context_info{
      agent_runner_.get(), config_accessor_.sessionmgr_config().session_agents()};
  session_shell_component_context_impl_ = std::make_unique<ComponentContextImpl>(
      component_context_info, session_shell_url_, session_shell_url_);
  OnTerminate(Reset(&session_shell_component_context_impl_));

  // |service_list| enumerates which services are made available to the session
  // shell.
  auto service_list = fuchsia::sys::ServiceList::New();
  for (const auto& service_name : agent_runner_->GetAgentServices()) {
    service_list->names.push_back(service_name);
  }

  agent_runner_->PublishAgentServices(session_shell_url_, &session_shell_services_);

  service_list->names.push_back(fuchsia::modular::SessionShellContext::Name_);
  session_shell_services_.AddService<fuchsia::modular::SessionShellContext>([this](auto request) {
    if (terminating_) {
      request.Close(ZX_ERR_UNAVAILABLE);
      return;
    }
    session_shell_context_bindings_.AddBinding(this, std::move(request));
  });

  service_list->names.push_back(fuchsia::modular::ComponentContext::Name_);
  session_shell_services_.AddService<fuchsia::modular::ComponentContext>([this](auto request) {
    if (terminating_) {
      request.Close(ZX_ERR_UNAVAILABLE);
      return;
    }
    session_shell_component_context_impl_->Connect(std::move(request));
  });

  service_list->names.push_back(fuchsia::modular::PuppetMaster::Name_);
  session_shell_services_.AddService<fuchsia::modular::PuppetMaster>([this](auto request) {
    if (terminating_) {
      request.Close(ZX_ERR_UNAVAILABLE);
      return;
    }
    puppet_master_impl_->Connect(std::move(request));
  });

  service_list->names.push_back(fuchsia::element::Manager::Name_);
  session_shell_services_.AddService<fuchsia::element::Manager>([this](auto request) {
    if (terminating_) {
      request.Close(ZX_ERR_UNAVAILABLE);
      return;
    }
    element_manager_impl_->Connect(std::move(request));
  });

  // The services in |session_shell_services_| are provided through the
  // connection held in |session_shell_service_provider| connected to
  // |session_shell_services_|.
  {
    fuchsia::sys::ServiceProviderPtr session_shell_service_provider;
    session_shell_services_.AddBinding(session_shell_service_provider.NewRequest());
    service_list->provider = std::move(session_shell_service_provider);
  }

  auto session_shell_app = std::make_unique<AppClient<fuchsia::modular::Lifecycle>>(
      session_environment_->GetLauncher(), std::move(session_shell_config),
      /* data_origin = */ "", std::move(service_list));

  auto [view_token, view_holder_token] = scenic::ViewTokenPair::New();
  fuchsia::ui::app::ViewProviderPtr view_provider;
  session_shell_app->services().ConnectToService(view_provider.NewRequest());
  scenic::ViewRefPair view_ref_pair = scenic::ViewRefPair::New();
  view_provider->CreateViewWithViewRef(std::move(view_token.value),
                                       std::move(view_ref_pair.control_ref),
                                       std::move(view_ref_pair.view_ref));
  session_shell_view_host_->ConnectView(std::move(view_holder_token));

  agent_runner_->AddRunningAgent(session_shell_url_, std::move(session_shell_app));
}

void SessionmgrImpl::Terminate(fit::function<void()> done) {
  FX_LOGS(INFO) << "Sessionmgr::Terminate()";
  terminating_ = true;
  terminate_done_ = std::move(done);

  TerminateRecurse(on_terminate_cbs_.size() - 1);
}

void SessionmgrImpl::GetComponentContext(
    fidl::InterfaceRequest<fuchsia::modular::ComponentContext> request) {
  session_shell_component_context_impl_->Connect(std::move(request));
}

void SessionmgrImpl::GetPresentation(
    fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> request) {
  session_context_->GetPresentation(std::move(request));
}

void SessionmgrImpl::GetStoryProvider(
    fidl::InterfaceRequest<fuchsia::modular::StoryProvider> request) {
  story_provider_impl_->Connect(std::move(request));
}

void SessionmgrImpl::Logout() { Restart(); }

void SessionmgrImpl::Restart() { session_context_->Restart(); }

void SessionmgrImpl::RestartDueToCriticalFailure() {
  session_context_->RestartDueToCriticalFailure();
}

void SessionmgrImpl::OnTerminate(fit::function<void(fit::function<void()>)> action) {
  on_terminate_cbs_.emplace_back(std::move(action));
}

void SessionmgrImpl::TerminateRecurse(const int i) {
  if (i >= 0) {
    on_terminate_cbs_[i]([this, i] { TerminateRecurse(i - 1); });
  } else {
    FX_LOGS(INFO) << "Sessionmgr::Terminate(): done";
    terminate_done_();
  }
}

}  // namespace modular
