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

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

namespace modular {

SessionCtlApp::SessionCtlApp(
    fuchsia::modular::internal::BasemgrDebug* const basemgr,
    fuchsia::modular::PuppetMaster* const puppet_master,
    const modular::Logger& logger, async_dispatcher_t* const dispatcher,
    const std::function<void()>& on_command_executed)
    : basemgr_(basemgr),
      puppet_master_(puppet_master),
      logger_(logger),
      dispatcher_(dispatcher),
      on_command_executed_(on_command_executed) {}

std::string SessionCtlApp::ExecuteCommand(
    std::string cmd, const fxl::CommandLine& command_line) {
  if (cmd == kAddModCommandString) {
    return ExecuteAddModCommand(command_line);
  } else if (cmd == kRemoveModCommandString) {
    return ExecuteRemoveModCommand(command_line);
  } else if (cmd == kDeleteStoryCommandString) {
    return ExecuteDeleteStoryCommand(command_line);
  } else if (cmd == kListStoriesCommandString) {
    return ExecuteListStoriesCommand();
  } else if (cmd == kRestartSessionCommandString) {
    return ExecuteRestartSessionCommand();
  } else {
    return kGetUsageErrorString;
  }
}

std::string SessionCtlApp::ExecuteRemoveModCommand(
    const fxl::CommandLine& command_line) {
  if (command_line.positional_args().size() == 1) {
    auto parsing_error =
        "Missing MOD_NAME. Ex: sessionctl remove_mod slider_mod";
    logger_.LogError(kRemoveModCommandString, parsing_error);
    return parsing_error;
  }

  // Get the mod name and default the story name to the mod name
  std::string mod_name = command_line.positional_args().at(1);
  std::string story_name = mod_name;

  // If the story_name flag isn't set, the story name will remain defaulted to
  // the mod name
  command_line.GetOptionValue(kStoryNameFlagString, &story_name);

  auto commands = MakeRemoveModCommands(mod_name);

  std::map<std::string, std::string> params = {
      {kModNameFlagString, mod_name}, {kStoryNameFlagString, story_name}};

  puppet_master_->ControlStory(story_name, story_puppet_master_.NewRequest());
  PostTaskExecuteStoryCommand(kRemoveModCommandString, std::move(commands),
                              params);

  return "";
}

std::string SessionCtlApp::ExecuteAddModCommand(
    const fxl::CommandLine& command_line) {
  if (command_line.positional_args().size() == 1) {
    auto parsing_error = "Missing MOD_URL. Ex: sessionctl add_mod slider_mod";
    logger_.LogError(kAddModCommandString, parsing_error);
    return parsing_error;
  }

  // Get the mod url and default the mod name and story name to the mod url
  std::string mod_url = command_line.positional_args().at(1);
  std::string mod_name = mod_url;
  std::string story_name = mod_url;

  if (mod_url.find(kFuchsiaPkgPrefix) == 0) {
    // Extract the component name from the mod url and use it as the mod and
    // story name
    std::regex pkg_regex(".*#meta/(\\w+)\\.cmx");
    std::smatch match;
    if (std::regex_search(mod_url, match, pkg_regex)) {
      mod_name = match[1];
      story_name = match[1];
    }
  } else {
    // Replace mod url short name with full package path
    mod_url =
        fxl::StringPrintf(kFuchsiaPkgPath, mod_url.c_str(), mod_url.c_str());
  }

  // If the following options aren't specified, their respective values will
  // remain unchanged.
  command_line.GetOptionValue(kStoryNameFlagString, &story_name);
  command_line.GetOptionValue(kModNameFlagString, &mod_name);

  auto commands = MakeAddModCommands(mod_url, mod_name);

  // Focus the mod and story by default
  std::string focus_mod;
  command_line.GetOptionValue(kFocusModFlagString, &focus_mod);
  if (focus_mod == "" || focus_mod == "true") {
    commands.push_back(MakeFocusModCommand(mod_name));
  }

  std::string focus_story;
  command_line.GetOptionValue(kFocusStoryFlagString, &focus_story);
  if (focus_story == "" || focus_story == "true") {
    commands.push_back(MakeFocusStoryCommand());
  }

  std::map<std::string, std::string> params = {
      {kModUrlFlagString, mod_url},
      {kModNameFlagString, mod_name},
      {kStoryNameFlagString, story_name}};

  puppet_master_->ControlStory(story_name, story_puppet_master_.NewRequest());
  PostTaskExecuteStoryCommand(kAddModCommandString, std::move(commands),
                              params);

  return "";
}

std::string SessionCtlApp::ExecuteDeleteStoryCommand(
    const fxl::CommandLine& command_line) {
  if (command_line.positional_args().size() == 1) {
    auto parsing_error =
        "Missing STORY_NAME. Ex. sessionctl delete_story story";
    logger_.LogError(kStoryNameFlagString, parsing_error);
    return parsing_error;
  }

  // Get the story name
  std::string story_name = command_line.positional_args().at(1);

  std::map<std::string, std::string> params = {
      {kStoryNameFlagString, story_name}};

  async::PostTask(dispatcher_, [this, story_name, params]() mutable {
    puppet_master_->DeleteStory(story_name, [this, params] {
      logger_.Log(kDeleteStoryCommandString, params);
      on_command_executed_();
    });
  });

  return "";
}

std::string SessionCtlApp::ExecuteListStoriesCommand() {
  async::PostTask(dispatcher_, [this]() mutable {
    puppet_master_->GetStories([this](std::vector<std::string> story_names) {
      logger_.Log(kListStoriesCommandString, std::move(story_names));
      on_command_executed_();
    });
  });

  return "";
}

std::string SessionCtlApp::ExecuteRestartSessionCommand() {
  basemgr_->RestartSession();
  logger_.Log(kRestartSessionCommandString, std::vector<std::string>());
  on_command_executed_();

  return "";
}

fuchsia::modular::StoryCommand SessionCtlApp::MakeFocusStoryCommand() {
  fuchsia::modular::StoryCommand command;
  fuchsia::modular::SetFocusState set_focus_state;
  set_focus_state.focused = true;
  command.set_set_focus_state(std::move(set_focus_state));
  return command;
}

fuchsia::modular::StoryCommand SessionCtlApp::MakeFocusModCommand(
    const std::string& mod_name) {
  fuchsia::modular::StoryCommand command;
  fuchsia::modular::FocusMod focus_mod;
  focus_mod.mod_name.push_back(mod_name);
  command.set_focus_mod(std::move(focus_mod));
  return command;
}

std::vector<fuchsia::modular::StoryCommand> SessionCtlApp::MakeAddModCommands(
    const std::string& mod_url, const std::string& mod_name) {
  fuchsia::modular::Intent intent;
  intent.handler = mod_url;

  std::vector<fuchsia::modular::StoryCommand> commands;
  fuchsia::modular::StoryCommand command;

  // Add command to add or update the mod (it will be updated if the mod_name
  // already exists in the story).
  fuchsia::modular::AddMod add_mod;
  add_mod.mod_name.push_back(mod_name);
  intent.Clone(&add_mod.intent);
  // TODO(MI4-953): Sessionctl takes in inital intent and other fields.

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

  return commands;
}

std::vector<fuchsia::modular::StoryCommand>
SessionCtlApp::MakeRemoveModCommands(const std::string& mod_name) {
  std::vector<fuchsia::modular::StoryCommand> commands;
  fuchsia::modular::StoryCommand command;

  fuchsia::modular::RemoveMod remove_mod;
  remove_mod.mod_name.push_back(mod_name);
  command.set_remove_mod(std::move(remove_mod));
  commands.push_back(std::move(command));
  return commands;
}

void SessionCtlApp::PostTaskExecuteStoryCommand(
    const std::string command_name,
    std::vector<fuchsia::modular::StoryCommand> commands,
    std::map<std::string, std::string> params) {
  async::PostTask(dispatcher_, [this, command_name,
                                commands = std::move(commands),
                                params]() mutable {
    ExecuteStoryCommand(std::move(commands), params.at(kStoryNameFlagString))
        ->Then(
            [this, command_name, params](bool has_error, std::string result) {
              if (has_error) {
                logger_.LogError(command_name, result);
              } else {
                auto params_copy = params;
                params_copy.emplace(kStoryIdFlagString, result);
                logger_.Log(command_name, params_copy);
              }
              on_command_executed_();
            });
  });
}

modular::FuturePtr<bool, std::string> SessionCtlApp::ExecuteStoryCommand(
    std::vector<fuchsia::modular::StoryCommand> commands,
    const std::string& story_name) {
  story_puppet_master_->Enqueue(std::move(commands));

  auto fut = modular::Future<bool, std::string>::Create(
      "Sessionctl StoryPuppetMaster::Execute");

  story_puppet_master_->Execute(fxl::MakeCopyable(
      [this, fut](fuchsia::modular::ExecuteResult result) mutable {
        if (result.status == fuchsia::modular::ExecuteStatus::OK) {
          fut->Complete(false, result.story_id->c_str());
        } else {
          std::string error = fxl::StringPrintf(
              "Puppet master returned status: %d and error: %s",
              (uint32_t)result.status, result.error_message->c_str());

          FXL_LOG(WARNING) << error << std::endl;
          fut->Complete(true, std::move(error));
        }
      }));

  return fut;
}

}  // namespace modular
