// 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 <optional>
#include <string>
#include <unordered_map>
#include <vector>

#include "kudu/gutil/strings/stringpiece.h"
#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.
    std::optional<std::string> default_value;
    // A description to override the gflag description.
    std::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.
  std::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,
      std::optional<std::string> default_value = std::nullopt,
      std::optional<std::string> description = std::nullopt);

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

 protected:
  const std::string name_;

  std::string description_;

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

  std::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 std::optional<std::string>& extra_description() const {
    return extra_description_;
  }

  const std::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_;

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

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

  ActionRunner runner_;

  ActionArgsDescriptor args_;
};

// Append 'to_append' to 'dst', but hard-wrapped at 78 columns.
// After any newline, 'continuation_indent' spaces are prepended.
void AppendHardWrapped(StringPiece to_append,
                       int continuation_indent,
                       std::string* dst);

// 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> BuildTxnMode();
std::unique_ptr<Mode> BuildTServerMode();
std::unique_ptr<Mode> BuildWalMode();

} // namespace tools
} // namespace kudu
