// 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);

  // 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);

  // 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.
  std::unique_ptr<Action> Build();

 private:
  const std::string name_;

  std::string description_;

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

  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 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_;

  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
