// 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.

// Implementation of a session shell for module development. It takes a
// root module URL and data for its fuchsia::modular::Link as command line
// arguments, which can be set using the basemgr --user-shell-args flag.

#include <memory>
#include <utility>

#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <fuchsia/ui/viewsv1/cpp/fidl.h>
#include <fuchsia/ui/viewsv1token/cpp/fidl.h>
#include <lib/app_driver/cpp/app_driver.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/component/cpp/connect.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/command_line.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/macros.h>
#include <zx/eventpair.h>

#include "peridot/lib/common/names.h"
#include "peridot/lib/fidl/single_service_app.h"
#include "peridot/lib/fidl/view_host.h"
#include "peridot/lib/rapidjson/rapidjson.h"
#include "peridot/lib/testing/test_driver.h"

namespace {

class Settings {
 public:
  explicit Settings(const fxl::CommandLine& command_line) {
    root_module =
        command_line.GetOptionValueWithDefault("root_module", "example_recipe");
    root_link = command_line.GetOptionValueWithDefault("root_link", "");
    story_id = command_line.GetOptionValueWithDefault("story_id", "story");
    module_under_test_url =
        command_line.GetOptionValueWithDefault("module_under_test_url", "");
    test_driver_url =
        command_line.GetOptionValueWithDefault("test_driver_url", "");
  }

  std::string root_module;
  std::string root_link;
  std::string story_id;
  std::string module_under_test_url;
  std::string test_driver_url;
};

class DevSessionShellApp : fuchsia::modular::StoryWatcher,
                           fuchsia::modular::InterruptionListener,
                           fuchsia::modular::NextListener,
                           public modular::ViewApp {
 public:
  explicit DevSessionShellApp(component::StartupContext* const startup_context,
                              Settings settings)
      : ViewApp(startup_context),
        settings_(std::move(settings)),
        story_watcher_binding_(this) {
    puppet_master_ =
        startup_context
            ->ConnectToEnvironmentService<fuchsia::modular::PuppetMaster>();
    session_shell_context_ = startup_context->ConnectToEnvironmentService<
        fuchsia::modular::SessionShellContext>();
    session_shell_context_->GetStoryProvider(story_provider_.NewRequest());
    session_shell_context_->GetSuggestionProvider(
        suggestion_provider_.NewRequest());
    session_shell_context_->GetFocusController(focus_controller_.NewRequest());
    session_shell_context_->GetVisibleStoriesController(
        visible_stories_controller_.NewRequest());

    suggestion_provider_->SubscribeToInterruptions(
        interruption_listener_bindings_.AddBinding(this));
    suggestion_provider_->SubscribeToNext(
        next_listener_bindings_.AddBinding(this), 3);
  }

  ~DevSessionShellApp() override = default;

 private:
  // |ViewApp|
  void CreateView(
      zx::eventpair view_token,
      fidl::InterfaceRequest<
          fuchsia::sys::ServiceProvider> /*incoming_services*/,
      fidl::InterfaceHandle<
          fuchsia::sys::ServiceProvider> /*outgoing_services*/) override {
    view_token_ = std::move(view_token);

    Connect();
  }

  void Connect() {
    FXL_CHECK(!!view_token_);
    FXL_CHECK(!!story_provider_);
    FXL_CHECK(!!puppet_master_);
    FXL_LOG(INFO) << "DevSessionShell START " << settings_.root_module << " "
                  << settings_.root_link;

    auto scenic =
        startup_context()
            ->ConnectToEnvironmentService<fuchsia::ui::scenic::Scenic>();
    scenic::ViewContext context = {
        .session_and_listener_request =
            scenic::CreateScenicSessionPtrAndListenerRequest(scenic.get()),
        .view_token = std::move(view_token_),
        .startup_context = startup_context(),
    };

    view_ = std::make_unique<modular::ViewHost>(std::move(context));

    puppet_master_->ControlStory(settings_.story_id,
                                 story_puppet_master_.NewRequest());

    fidl::VectorPtr<fuchsia::modular::StoryCommand> commands;
    fuchsia::modular::AddMod add_mod;
    add_mod.mod_name.push_back("root");
    add_mod.intent.handler = settings_.root_module;
    add_mod.intent.action = "action";
    add_mod.intent.parameters = CreateIntentParameters();

    fuchsia::modular::StoryCommand command;
    command.set_add_mod(std::move(add_mod));
    commands.push_back(std::move(command));

    story_puppet_master_->Enqueue(std::move(commands));
    story_puppet_master_->Execute(
        [this](fuchsia::modular::ExecuteResult result) {
          StartStoryById(settings_.story_id);
        });
  }

  fidl::VectorPtr<fuchsia::modular::IntentParameter> CreateIntentParameters() {
    if (settings_.module_under_test_url.empty() ||
        settings_.test_driver_url.empty()) {
      // For debugging: log that both items must be set in the event that one is
      // set and the other is not. It may be unclear why the intent is not being
      // created with the intended links if one is forgotten by accident.
      if (settings_.module_under_test_url.empty() !=
          settings_.test_driver_url.empty()) {
        FXL_LOG(WARNING) << "Both the module_under_test_url and "
                            "test_driver_url must be set";
      }
      return nullptr;
    }
    auto intent_params =
        fidl::VectorPtr<fuchsia::modular::IntentParameter>::New(0);
    fuchsia::modular::IntentParameterData test_driver_link_data;

    rapidjson::Document document;
    document.SetObject();
    document.AddMember(modular::testing::kModuleUnderTestPath,
                       settings_.module_under_test_url,
                       document.GetAllocator());
    document.AddMember(modular::testing::kTestDriverPath,
                       settings_.test_driver_url, document.GetAllocator());
    fsl::SizedVmo vmo;
    FXL_CHECK(fsl::VmoFromString(modular::JsonValueToString(document), &vmo));
    test_driver_link_data.set_json(std::move(vmo).ToTransport());

    fuchsia::modular::IntentParameter test_driver_link_param;
    test_driver_link_param.name = modular::testing::kTestDriverLinkName;
    test_driver_link_param.data = std::move(test_driver_link_data);
    intent_params.push_back(std::move(test_driver_link_param));

    return intent_params;
  }

  void StartStoryById(const fidl::StringPtr& story_id) {
    story_provider_->GetController(story_id, story_controller_.NewRequest());
    story_controller_.set_error_handler([this, story_id](zx_status_t status) {
      FXL_LOG(ERROR) << "Story controller for story " << story_id
                     << " died. Does this story exist?";
    });

    story_controller_->Watch(story_watcher_binding_.NewBinding());

    FXL_LOG(INFO) << "DevSessionShell Starting story with id: " << story_id;
    fidl::InterfaceHandle<fuchsia::ui::viewsv1token::ViewOwner>
        root_module_view;
    story_controller_->Start(root_module_view.NewRequest());
    view_->ConnectView(std::move(root_module_view));
    focus_controller_->Set(story_id);
    auto visible_stories = fidl::VectorPtr<fidl::StringPtr>::New(0);
    visible_stories.push_back(story_id);
    visible_stories_controller_->Set(std::move(visible_stories));

    if (!settings_.root_link.empty()) {
      fuchsia::modular::LinkPtr root;

      fuchsia::modular::LinkPath link_path = fuchsia::modular::LinkPath();
      link_path.module_path = ::fidl::VectorPtr<::fidl::StringPtr>::New(0);
      link_path.link_name = "root";
      story_controller_->GetLink(std::move(link_path), root.NewRequest());

      fsl::SizedVmo vmo;
      FXL_CHECK(fsl::VmoFromString(settings_.root_link, &vmo));
      root->Set(nullptr, std::move(vmo).ToTransport());
    }
  }

  // |fuchsia::modular::StoryWatcher|
  void OnStateChange(fuchsia::modular::StoryState state) override {
    FXL_LOG(INFO) << "DevSessionShell State " << fidl::ToUnderlying(state);
  }

  // |fuchsia::modular::StoryWatcher|
  void OnModuleAdded(fuchsia::modular::ModuleData /*module_data*/) override {}

  // |fuchsia::modular::StoryWatcher|
  void OnModuleFocused(
      fidl::VectorPtr<fidl::StringPtr> /*module_path*/) override {}

  // |fuchsia::modular::NextListener|
  void OnNextResults(
      fidl::VectorPtr<fuchsia::modular::Suggestion> suggestions) override {
    FXL_VLOG(4)
        << "DevSessionShell/fuchsia::modular::NextListener::OnNextResults()";
    for (auto& suggestion : *suggestions) {
      FXL_LOG(INFO) << "  " << suggestion.uuid << " "
                    << suggestion.display.headline;
    }
  }

  // |fuchsia::modular::InterruptionListener|
  void OnInterrupt(fuchsia::modular::Suggestion suggestion) override {
    FXL_VLOG(4) << "DevSessionShell/"
                   "fuchsia::modular::InterruptionListener::OnInterrupt() "
                << suggestion.uuid;
  }

  // |fuchsia::modular::NextListener|
  void OnProcessingChange(bool processing) override {
    FXL_VLOG(4)
        << "DevSessionShell/fuchsia::modular::NextListener::OnProcessingChange("
        << processing << ")";
  }

  const Settings settings_;

  zx::eventpair view_token_;
  std::unique_ptr<modular::ViewHost> view_;

  fuchsia::modular::SessionShellContextPtr session_shell_context_;
  fuchsia::modular::PuppetMasterPtr puppet_master_;
  fuchsia::modular::StoryPuppetMasterPtr story_puppet_master_;
  fuchsia::modular::StoryProviderPtr story_provider_;
  fuchsia::modular::StoryControllerPtr story_controller_;
  fuchsia::modular::FocusControllerPtr focus_controller_;
  fuchsia::modular::VisibleStoriesControllerPtr visible_stories_controller_;

  fidl::Binding<fuchsia::modular::StoryWatcher> story_watcher_binding_;

  fuchsia::modular::SuggestionProviderPtr suggestion_provider_;
  fidl::BindingSet<fuchsia::modular::InterruptionListener>
      interruption_listener_bindings_;
  fidl::BindingSet<fuchsia::modular::NextListener> next_listener_bindings_;

  FXL_DISALLOW_COPY_AND_ASSIGN(DevSessionShellApp);
};

}  // namespace

int main(int argc, const char** argv) {
  auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
  Settings settings(command_line);

  async::Loop loop(&kAsyncLoopConfigAttachToThread);

  auto context = component::StartupContext::CreateFromStartupInfo();
  modular::AppDriver<DevSessionShellApp> driver(
      context->outgoing().deprecated_services(),
      std::make_unique<DevSessionShellApp>(context.get(), std::move(settings)),
      [&loop] { loop.Quit(); });

  loop.Run();
  return 0;
}
