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

#ifndef PERIDOT_BIN_SESSIONCTL_SESSION_CTL_APP_H_
#define PERIDOT_BIN_SESSIONCTL_SESSION_CTL_APP_H_

#include <iostream>
#include <string>

#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 <src/lib/fxl/command_line.h>
#include <src/lib/fxl/strings/string_printf.h>

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

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

namespace modular {

class SessionCtlApp {
 public:
  // Constructs a SessionCtlApp which can read and execute session commands.
  // |puppet_master| The interface used to execute commands.
  // |basemgr| The basemgr to use to restart sessions.
  // |command_line| The command line used to read commands and arguments.
  // |logger| The logger used to log the results of commands.
  // |dispatcher| The dispatcher which is used to post the command tasks.
  // |on_command_executed| A callback which is called whenever a command has
  // finished executing.
  explicit SessionCtlApp(fuchsia::modular::internal::BasemgrDebug* const basemgr,
                         fuchsia::modular::PuppetMaster* const puppet_master,
                         const modular::Logger& logger, async_dispatcher_t* const dispatcher);

  // Dispatches the |cmd|. Calls |done| when done with an empty string if
  // execution was successful or with an error string on failure.
  void ExecuteCommand(std::string cmd, const fxl::CommandLine& command_line,
                      fit::function<void(std::string error)> done);

 private:
  // Executes the respective command and returns an empty string on success and
  // a string of missing flags on failure.
  void ExecuteAddModCommand(const fxl::CommandLine& command_line,
                            fit::function<void(std::string)> done);
  void ExecuteRemoveModCommand(const fxl::CommandLine& command_line,
                               fit::function<void(std::string)> done);
  void ExecuteDeleteStoryCommand(const fxl::CommandLine& command_line,
                                 fit::function<void(std::string)> done);
  void ExecuteDeleteAllStoriesCommand(fit::function<void(std::string)> done);
  void ExecuteListStoriesCommand(fit::function<void(std::string)> done);
  void ExecuteRestartSessionCommand(fit::function<void(std::string)> done);
  void ExecuteSelectNextSessionShellCommand(const fxl::CommandLine& command_line,
                                            fit::function<void(std::string)> done);

  // Focus the story to which the mod we are adding belongs.
  fuchsia::modular::StoryCommand MakeFocusStoryCommand();

  // Focus the mod we just added. This is not necessary when adding a new mod
  // since it will be always focused. However, when a mod is updated it might
  // not be focused.
  fuchsia::modular::StoryCommand MakeFocusModCommand(const std::string& mod_name);

  std::vector<fuchsia::modular::StoryCommand> MakeAddModCommands(const std::string& mod_url,
                                                                 const std::string& mod_name);

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

  // Does a PostTask to Execute the commands on StoryPuppetMaster.
  // When the commands are executed do logging and then call
  // on_command_executed_() callback.
  // |command_name| the string command name.
  // |commands| the StoryCommands to execute on StoryPuppetMaster.
  // |params| map of {command_line arg : command_line value}. Used for logging.
  void PostTaskExecuteStoryCommand(const std::string command_name,
                                   std::vector<fuchsia::modular::StoryCommand> commands,
                                   std::map<std::string, std::string> params,
                                   fit::function<void(std::string)> done);

  modular::FuturePtr<bool, std::string> ExecuteStoryCommand(
      std::vector<fuchsia::modular::StoryCommand> commands, const std::string& story_name);

  std::string GenerateMissingFlagString(const std::vector<std::string>& missing_flags);

  fuchsia::modular::internal::BasemgrDebug* const basemgr_;
  fuchsia::modular::PuppetMaster* const puppet_master_;
  fuchsia::modular::StoryPuppetMasterPtr story_puppet_master_;
  const fxl::CommandLine command_line_;
  const modular::Logger logger_;
  async_dispatcher_t* const dispatcher_;
  fit::function<void()> on_command_executed_;
};

}  // namespace modular

#endif  // PERIDOT_BIN_SESSIONCTL_SESSION_CTL_APP_H_
