// Copyright 2018 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 <dirent.h>
#include <glob.h>
#include <sys/types.h>
#include <iostream>
#include <regex>
#include <string>
#include <vector>

#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/modular/internal/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/future.h>
#include <lib/async/cpp/task.h>
#include <lib/fdio/util.h>
#include <lib/fxl/command_line.h>
#include <lib/fxl/files/file.h>
#include <lib/fxl/log_settings_command_line.h>
#include <lib/fxl/strings/string_printf.h>
#include "lib/fxl/functional/make_copyable.h"

#include "peridot/bin/sessionctl/logger.h"
#include "peridot/bin/sessionctl/session_ctl_app.h"
#include "peridot/bin/sessionctl/session_ctl_constants.h"

using ::fuchsia::modular::PuppetMaster;
using ::fuchsia::modular::PuppetMasterPtr;

struct DebugService {
  std::string name;
  std::string service_path;
};

std::string GetUsage() {
  return R"(sessionctl <flags> <command> <argument>
Example:
sessionctl add_mod slider_mod

sessionctl --mod_name=mod1 --story_name=story1 --focus_mod=false
            --focus_story=false add_mod slider_mod

sessionctl --story_name=story1 remove_mod slider_mod

<flags>
--story_name=STORY_NAME
--mod_name=MOD_NAME
--focus_mod=false
    Don't focus the mod.
--focus_story=false
    Don't focus the story.
--json_out
    If flag is set output json for consuming instead of text.

<command>
add_mod
  Usage: [--story_name=foo] [--mod_name=bar] [--focus_mod=false] [--focus_story=false] add_mod MOD_URL

  Add a new mod or update an existing mod if a mod with --mod_name already
  exists in --story_name.
  Defaults --story_name and --mod_name to MOD_URL.
  Defaults --focus_mod and --focus_story to 'true'.

  MOD_URL
    Mods have a unique "mod_url". It's the mod package's name.
    In BUILD.gn fuchsia_package_name = "mod_url" or mod_url comes from
    flutter_app("mod_url") when there is no fuchsia_package_name set.

  optional: --story_name, --mod_name, --focus_mod, --focus_story

remove_mod
  Usage: [--story_name=foo] remove_mod MOD_NAME

  Removes an existing mod by name. If the mod was added with add_mod, 
  use the value you passed to add_mod's --mod_name flag or the default
  value which would be the mod_url.
  Defaults --story_name to MOD_NAME.

  MOD_NAME
      The name of the mod.

  optional: --story_name

delete_story
  Usage: delete_story STORY_NAME

  Deletes the story.

  STORY_NAME
    The name of the story.

list_stories
  List all the stories in the current session.

restart_session
  Restarts the current session.)";
}

void FindDebugServicesForPath(const char* glob_str, const char* regex_str,
                              std::vector<DebugService>* services) {
  glob_t globbuf;
  bool service_exists = glob(glob_str, 0, nullptr, &globbuf) == 0;
  std::regex name_regex(regex_str);
  if (service_exists) {
    for (size_t i = 0; i < globbuf.gl_pathc; ++i) {
      DebugService s;
      s.service_path = globbuf.gl_pathv[i];
      std::smatch match;
      FXL_CHECK(std::regex_search(s.service_path, match, name_regex))
          << s.service_path;
      s.name = match[1];
      services->push_back(std::move(s));
    }
    globfree(&globbuf);
  }
}

// Returns a list of all running sessions.
std::vector<DebugService> FindAllSessions() {
  const char kRegex[] = "/sessionmgr.cmx/(\\d+)";
  // See peridot/bin/sessionmgr/sessionmgr_impl.cc's definition of
  // kSessionCtlDir for "sessionctl". These must match.
  std::vector<DebugService> sessions;
  FindDebugServicesForPath("/hub/c/sessionmgr.cmx/*/out/debug/sessionctl",
                           kRegex, &sessions);

  FindDebugServicesForPath(
      "/hub/r/sys/*/c/sessionmgr.cmx/*/out/debug/sessionctl", kRegex,
      &sessions);
  return sessions;
}

PuppetMasterPtr ConnectToPuppetMaster(const DebugService& session) {
  PuppetMasterPtr puppet_master;
  auto request = puppet_master.NewRequest().TakeChannel();
  std::string service_path = session.service_path + "/" + PuppetMaster::Name_;
  if (fdio_service_connect(service_path.c_str(), request.get()) != ZX_OK) {
    FXL_LOG(FATAL) << "Could not connect to PuppetMaster service in "
                   << session.service_path;
  }
  return puppet_master;
}

fuchsia::modular::internal::BasemgrDebugPtr ConnectToBasemgr() {
  fuchsia::modular::internal::BasemgrDebugPtr basemgr;
  auto request = basemgr.NewRequest().TakeChannel();

  std::vector<DebugService> services;
  FindDebugServicesForPath("/hub/c/basemgr.cmx/*/out/debug/basemgr",
                           "basemgr.cmx", &services);

  if (services.empty()) {
    return nullptr;
  }
  FXL_CHECK(services.size() == 1);

  std::string service_path = services[0].service_path;
  if (fdio_service_connect(service_path.c_str(), request.get()) != ZX_OK) {
    FXL_LOG(FATAL) << "Could not connect to basemgr service in "
                   << service_path;
  }

  return basemgr;
}

int main(int argc, const char** argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToThread);

  const auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
  fxl::SetLogSettingsFromCommandLine(command_line);
  const auto& positional_args = command_line.positional_args();
  const auto& cmd = positional_args.empty() ? "" : positional_args[0];

  const modular::Logger logger(
      command_line.HasOption(modular::kJsonOutFlagString));

  auto basemgr = ConnectToBasemgr();
  if (!basemgr) {
    logger.LogError(cmd, "Could not find a running basemgr. Is it running?");
    return 1;
  }

  auto sessions = FindAllSessions();
  if (sessions.empty()) {
    logger.LogError(
        cmd, "Could not find a running sessionmgr. Is the user logged in?");
    return 1;
  }

  if (!command_line.HasOption(modular::kJsonOutFlagString)) {
    std::cout << "Found the following sessions:\n\n";
    for (const auto& session : sessions) {
      std::cout << "\t" << session.name << ": " << session.service_path
                << std::endl;
    }
    std::cout << std::endl;
  }

  // To get a PuppetMaster service for a session, use the following code:
  PuppetMasterPtr puppet_master = ConnectToPuppetMaster(sessions[0]);

  modular::SessionCtlApp app(basemgr.get(), puppet_master.get(), logger,
                             loop.dispatcher(), [&loop] { loop.Quit(); });

  std::string parsing_error = app.ExecuteCommand(cmd, command_line);
  if (parsing_error == modular::kGetUsageErrorString) {
    // Print help if command doesn't match a valid command.
    std::cout << GetUsage() << std::endl;
    return 1;
  }

  if (!parsing_error.empty()) {
    return 1;
  }

  loop.Run();

  return 0;
}
