// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#pragma once

#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include <boost/optional/optional.hpp>

#include "kudu/util/status.h"

namespace kudu {
namespace tools {

class Action;
class Mode;

// The command line tool is structured as a tree with two kinds of nodes: modes
// and actions. Actions are leaf nodes, each representing a particular
// operation that the tool can take. Modes are non-leaf nodes that are
// basically just intuitive groupings of actions.
//
// Regardless of type, every node has a name which is used to match it against
// a command line argument during parsing. Additionally, every node has a
// description, displayed (along with the name) in help text.
//
// Every node (be it action or mode) has pointers to its children, but not to
// its parent mode. As such, operations that require information from the
// parent modes expect the caller to provide those modes as a "mode chain".
//
// Sample node tree:
//
//         root
//          |
//          |
//          fs
//         |  |
//      +--+  +--+
//      |        |
//   format    dump
//             | |
//         +--+  +--+
//         |        |
//      cfile      uuid
//
// Given this tree:
// - "<program> fs" will show all of fs's possible actions.
// - "<program> fs format" will format a filesystem.
// - "<program> fs dump uuid" will print a filesystem's UUID.

// Builds a new mode (non-leaf) node.
class ModeBuilder {
 public:
  // Creates a new ModeBuilder with a specific name (e.g. "fs"). The name
  // uniquely identifies the mode amongst its siblings in the tree.
  explicit ModeBuilder(std::string name);

  // Sets the description of this mode (e.g. "Operate on a local Kudu
  // filesystem"), to be used when printing help.
  //
  // Required.
  ModeBuilder& Description(const std::string& desc);

  // Adds a new mode (non-leaf child node) to this builder.
  ModeBuilder& AddMode(std::unique_ptr<Mode> mode);

  // Adds a new action (leaf child node) to this builder.
  ModeBuilder& AddAction(std::unique_ptr<Action> action);

  // Creates a mode using builder state.
  //
  // May only be called once.
  std::unique_ptr<Mode> Build();

 private:
  const std::string name_;

  std::string description_;

  std::vector<std::unique_ptr<Mode>> submodes_;

  std::vector<std::unique_ptr<Action>> actions_;
};

// A non-leaf node in the tree, representing a logical grouping for actions or
// more modes.
class Mode {
 public:

  // Returns the help for this mode given its parent mode chain.
  std::string BuildHelp(const std::vector<Mode*>& chain) const;

  // Returns the help xml for this mode and all child modes
  std::string BuildHelpXML(const std::vector<Mode*>& chain) const;

  const std::string& name() const { return name_; }

  const std::string& description() const { return description_; }

  const std::vector<std::unique_ptr<Mode>>& modes() const { return submodes_; }

  const std::vector<std::unique_ptr<Action>>& actions() const { return actions_; }

 private:
  friend class ModeBuilder;

  Mode() = default;

  std::string name_;

  std::string description_;

  std::vector<std::unique_ptr<Mode>> submodes_;

  std::vector<std::unique_ptr<Action>> actions_;
};

// Function signature for any operation represented by an Action.
//
// When run, the operation receives the parent mode chain, the current action,
// and the command line arguments.
//
// Prior to running, arguments registered by the action are put into the
// context. In the event that a required parameter is missing or there are
// unexpected arguments on the command line, an error is returned and the
// runner will not be invoked.
//
// Note: only required and variadic args are put in the context; it is expected
// that operations access optional args via gflag variables (i.e. FLAGS_foo).
struct RunnerContext {
  std::vector<Mode*> chain;
  const Action* action;
  std::unordered_map<std::string, std::string> required_args;
  std::vector<std::string> variadic_args;
};
typedef std::function<Status(const RunnerContext&)> ActionRunner;

// Describes all of the arguments used by an action. At runtime, the tool will
// parse these arguments out of the command line and marshal them into a
// key/value argument map (see Run()).
struct ActionArgsDescriptor {
  struct Arg {
    std::string name;
    std::string description;
  };

  // Holds an optional command line argument flag.
  struct Flag {
    // The gflag name.
    std::string name;
    // A default value to override the default gflag value.
    boost::optional<std::string> default_value;
    // A description to override the gflag description.
    boost::optional<std::string> description;
  };

  // Positional (required) command line arguments.
  std::vector<Arg> required;

  // Key-value command line arguments. These must correspond to defined gflags.
  //
  // Optional by definition, though some are required internally
  // (e.g. fs_wal_dir).
  std::vector<Flag> optional;

  // Variable length command line argument. There may be at most one per
  // Action, and it's always found at the end of the command line.
  boost::optional<Arg> variadic;
};

// Builds a new action (leaf) node.
class ActionBuilder {
 public:
  // Creates a new ActionBuilder with a specific name (e.g. "format") and
  // action runner. The name uniquely identifies the action amongst its
  // siblings in the tree.
  ActionBuilder(std::string name, ActionRunner runner);
  virtual ~ActionBuilder() = default;

  // Sets the description of this action (e.g. "Format a new Kudu filesystem"),
  // to be used when printing the parent mode's help and the action's help.
  //
  // Required.
  ActionBuilder& Description(const std::string& description);

  // Sets the long description of this action. If provided, will added to this
  // action's help following Description().
  ActionBuilder& ExtraDescription(const std::string& extra_description);

  // Sets the program name to use when running this action. If unset,
  // argv0 is used.
  //
  // This will ensure logging is initialized as if the program binary name was
  // the passed `program_name`.
  ActionBuilder& ProgramName(const std::string& program_name);

  // Add a new required parameter to this builder.
  //
  // This parameter will be parsed as a positional argument following the name
  // of the action. The order in which required parameters are added to the
  // builder reflects the order they are expected to be parsed from the command
  // line.
  ActionBuilder& AddRequiredParameter(
      const ActionArgsDescriptor::Arg& arg);

  // Add a new required variable-length parameter to this builder.
  //
  // This parameter will be parsed following all other positional parameters.
  // All remaining positional arguments on the command line will be parsed into
  // this parameter.
  //
  // There may be at most one variadic parameter defined per action.
  ActionBuilder& AddRequiredVariadicParameter(
      const ActionArgsDescriptor::Arg& arg);

  // Add a new optional parameter to this builder.
  //
  // This parameter will be parsed by the gflags system, and thus can be
  // provided by the user at any point in the command line. It must match a
  // previously-defined gflag; if a gflag with the same name cannot be found,
  // the tool will crash.
  //
  // The default value and description of the flag can be optionally overriden,
  // for cases where the values are action-dependent. Otherwise, the default
  // value and description from the gflag declaration will be used.
  ActionBuilder& AddOptionalParameter(std::string param,
                                      boost::optional<std::string> default_value = boost::none,
                                      boost::optional<std::string> description = boost::none);

  // Creates an action using builder state.
  virtual std::unique_ptr<Action> Build();

 protected:
  const std::string name_;

  std::string description_;

  boost::optional<std::string> extra_description_;

  boost::optional<std::string> program_name_;

  ActionRunner runner_;

  ActionArgsDescriptor args_;
};

// A leaf node in the tree, representing a logical operation taken by the tool.
class Action {
 public:
  enum HelpMode {
    // Return the full help text, including descriptions for each
    // of the arguments.
    FULL_HELP,
    // Return only a single-line usage statement.
    USAGE_ONLY
  };

  // Returns the help for this action given its parent mode chain.
  std::string BuildHelp(const std::vector<Mode*>& chain,
                        HelpMode mode = FULL_HELP) const;

  // Returns the help xml for this action
  std::string BuildHelpXML(const std::vector<Mode*>& chain) const;

  // Runs the operation represented by this action, given a parent mode chain
  // and marshaled command line arguments.
  Status Run(const std::vector<Mode*>& chain,
             const std::unordered_map<std::string, std::string>& required_args,
             const std::vector<std::string>& variadic_args) const;

  const std::string& name() const { return name_; }

  const std::string& description() const { return description_; }

  const boost::optional<std::string>& extra_description() const {
    return extra_description_;
  }

  const boost::optional<std::string>& program_name() const {
    return program_name_;
  }

  const ActionArgsDescriptor& args() const { return args_; }

 private:
  friend class ActionBuilder;

  Action() = default;

  // Sets optional flag parameter default value in cases where it has been
  // overridden from the default gflag value.
  void SetOptionalParameterDefaultValues() const;

  std::string name_;

  std::string description_;

  boost::optional<std::string> extra_description_;

  boost::optional<std::string> program_name_;

  ActionRunner runner_;

  ActionArgsDescriptor args_;
};

// Returns new nodes for each major mode.
std::unique_ptr<Mode> BuildClusterMode();
std::unique_ptr<Mode> BuildDiagnoseMode();
std::unique_ptr<Mode> BuildFsMode();
std::unique_ptr<Mode> BuildHmsMode();
std::unique_ptr<Mode> BuildLocalReplicaMode();
std::unique_ptr<Mode> BuildMasterMode();
std::unique_ptr<Mode> BuildPbcMode();
std::unique_ptr<Mode> BuildPerfMode();
std::unique_ptr<Mode> BuildRemoteReplicaMode();
std::unique_ptr<Mode> BuildTableMode();
std::unique_ptr<Mode> BuildTabletMode();
std::unique_ptr<Mode> BuildTestMode();
std::unique_ptr<Mode> BuildTServerMode();
std::unique_ptr<Mode> BuildWalMode();

} // namespace tools
} // namespace kudu
