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

#include "kudu/tools/tool_action.h"

#include <algorithm>
#include <cstddef>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "kudu/gutil/strings/join.h"
#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/stringpiece.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/util/flags.h"
#include "kudu/util/logging.h"
#include "kudu/util/url-coding.h"

using std::optional;
using std::pair;
using std::string;
using std::unique_ptr;
using std::unordered_map;
using std::vector;
using strings::Substitute;

namespace kudu {
namespace tools {

namespace {

string FakeDescribeOneFlag(const ActionArgsDescriptor::Arg& arg) {
  string res = google::DescribeOneFlag({
    arg.name,        // name
    "string",        // type
    arg.description, // description
    "",              // current_value
    "",              // default_value
    "",              // filename
    false,           // has_validator_fn
    true,            // is_default
    nullptr          // flag_ptr
  });

  // Strip the first dash from the description; this is a positional parameter
  // so let's make sure it looks like one.
  string::size_type first_dash_idx = res.find('-');
  DCHECK_NE(string::npos, first_dash_idx);
  return res.substr(0, first_dash_idx) + res.substr(first_dash_idx + 1);
}

string BuildUsageString(const vector<Mode*>& chain) {
  return JoinMapped(chain, [](Mode* a){ return a->name(); }, " ");
}

string SpacePad(StringPiece s, int len) {
  if (s.size() >= len) {
    return s.ToString();
  }
  return string(len - s.size(), ' ' ) + s.ToString();
}

} // anonymous namespace

ModeBuilder::ModeBuilder(string name)
    : name_(std::move(name)) {
}

ModeBuilder& ModeBuilder::Description(const string& description) {
  CHECK(description_.empty());
  description_ = description;
  return *this;
}

ModeBuilder& ModeBuilder::AddMode(unique_ptr<Mode> mode) {
  submodes_.push_back(std::move(mode));
  return *this;
}

ModeBuilder& ModeBuilder::AddAction(unique_ptr<Action> action) {
  actions_.push_back(std::move(action));
  return *this;
}

unique_ptr<Mode> ModeBuilder::Build() {
  CHECK(!description_.empty());
  unique_ptr<Mode> mode(new Mode());
  mode->name_ = name_;
  mode->description_ = description_;
  mode->submodes_ = std::move(submodes_);
  mode->actions_ = std::move(actions_);
  return mode;
}

// Get help for this mode, passing in its parent mode chain.
string Mode::BuildHelp(const vector<Mode*>& chain) const {
  string msg;
  msg += Substitute("Usage: $0 <command> [<args>]\n\n",
                    BuildUsageString(chain));
  msg += "<command> can be one of the following:\n";

  vector<pair<string, string>> line_pairs;
  int max_command_len = 0;
  for (const auto& m : modes()) {
    line_pairs.emplace_back(m->name(), m->description());
    max_command_len = std::max<int>(max_command_len, m->name().size());
  }
  for (const auto& a : actions()) {
    line_pairs.emplace_back(a->name(), a->description());
    max_command_len = std::max<int>(max_command_len, a->name().size());
  }

  for (const auto& lp : line_pairs) {
    msg += "  " + SpacePad(lp.first, max_command_len);
    msg += "   ";
    AppendHardWrapped(lp.second, max_command_len + 5, &msg);
    msg += "\n";
  }

  msg += "\n";
  return msg;
}

string Mode::BuildHelpXML(const vector<Mode*>& chain) const {
  string xml;
  xml += "<mode>";
  xml += Substitute("<name>$0</name>", name());
  xml += Substitute("<description>$0</description>",
                    EscapeForHtmlToString(description()));
  for (const auto& a : actions()) {
    xml += a->BuildHelpXML(chain);
  }

  for (const auto& m : modes()) {
    vector<Mode*> m_chain(chain);
    m_chain.push_back(m.get());
    xml += m->BuildHelpXML(m_chain);
  }
  xml += "</mode>";
  return xml;
}

ActionBuilder::ActionBuilder(string name, ActionRunner runner)
    : name_(std::move(name)),
      runner_(std::move(runner)) {
}

ActionBuilder& ActionBuilder::Description(const string& description) {
  CHECK(description_.empty());
  description_ = description;
  return *this;
}

ActionBuilder& ActionBuilder::ExtraDescription(const string& extra_description) {
  CHECK(!extra_description_.has_value());
  extra_description_ = extra_description;
  return *this;
}

ActionBuilder& ActionBuilder::ProgramName(const string& program_name) {
  CHECK(!program_name_.has_value());
  program_name_ = program_name;
  return *this;
}

ActionBuilder& ActionBuilder::AddRequiredParameter(
    const ActionArgsDescriptor::Arg& arg) {
  args_.required.push_back(arg);
  return *this;
}

ActionBuilder& ActionBuilder::AddRequiredVariadicParameter(
    const ActionArgsDescriptor::Arg& arg) {
  DCHECK(!args_.variadic);
  args_.variadic = arg;
  return *this;
}

ActionBuilder& ActionBuilder::AddOptionalParameter(
    string param,
    optional<std::string> default_value,
    optional<std::string> description) {
#ifndef NDEBUG
  // Make sure this gflag exists.
  string option;
  DCHECK(google::GetCommandLineOption(param.c_str(), &option)) << "unknown option: " << param;
#endif
  args_.optional.emplace_back(ActionArgsDescriptor::Flag({ std::move(param),
                                                           std::move(default_value),
                                                           std::move(description) }));
  return *this;
}

unique_ptr<Action> ActionBuilder::Build() {
  CHECK(!description_.empty());
  unique_ptr<Action> action(new Action());
  action->name_ = name_;
  action->description_ = description_;
  action->extra_description_ = extra_description_;
  action->program_name_ = program_name_;
  action->runner_ = runner_;
  action->args_ = args_;
  return action;
}

Status Action::Run(const vector<Mode*>& chain,
                   const unordered_map<string, string>& required_args,
                   const vector<string>& variadic_args) const {
  SetOptionalParameterDefaultValues();

  // If `program_name_` is defined,  initialize the logging as if the
  // program binary name was `program_name_`, otherwise fallback to the
  // default behavior of using argv0.
  if (program_name_) {
    CHECK_NE("", google::SetCommandLineOptionWithMode("log_filename",
        program_name_->c_str(),
        google::FlagSettingMode::SET_FLAGS_DEFAULT));
  }
  kudu::InitGoogleLoggingSafe(program_name_.value_or(gflags::GetArgv0()).c_str());
  kudu::ValidateFlags();

  return runner_({ chain, this, required_args, variadic_args });
}

string Action::BuildHelp(const vector<Mode*>& chain,
                         Action::HelpMode mode) const {
  SetOptionalParameterDefaultValues();
  string usage_msg = Substitute("Usage: $0 $1", BuildUsageString(chain), name());
  string desc_msg;
  for (const auto& param : args_.required) {
    usage_msg += Substitute(" <$0>", param.name);
    desc_msg += FakeDescribeOneFlag(param);
    desc_msg += "\n";
  }
  if (args_.variadic) {
    const ActionArgsDescriptor::Arg& param = *args_.variadic;
    usage_msg += Substitute(" <$0>...", param.name);
    desc_msg += FakeDescribeOneFlag(param);
    desc_msg += "\n";
  }
  for (const auto& param : args_.optional) {
    google::CommandLineFlagInfo gflag_info =
        google::GetCommandLineFlagInfoOrDie(param.name.c_str());

    if (param.description) {
      gflag_info.description = *param.description;
    }

    if (gflag_info.type == "bool") {
      if (gflag_info.default_value == "false") {
        usage_msg += Substitute(" [-$0]", param.name);
      } else {
        usage_msg += Substitute(" [-no$0]", param.name);
      }
    } else {
      string noun;
      string::size_type last_underscore_idx = param.name.rfind('_');
      if (last_underscore_idx != string::npos &&
          last_underscore_idx != param.name.size() - 1) {
        noun = param.name.substr(last_underscore_idx + 1);
      } else {
        noun = param.name;
      }
      usage_msg += Substitute(" [-$0=<$1>]", param.name, noun);
    }
    desc_msg += google::DescribeOneFlag(gflag_info);
    desc_msg += "\n";
  }
  if (mode == USAGE_ONLY) {
    return usage_msg;
  }
  string msg;
  AppendHardWrapped(usage_msg, 8, &msg);
  msg += "\n\n";
  AppendHardWrapped(description_, 0, &msg);
  if (extra_description_) {
    msg += "\n\n";
    AppendHardWrapped(*extra_description_, 0, &msg);
  }
  msg += "\n\n";
  msg += desc_msg;
  return msg;
}

string Action::BuildHelpXML(const vector<Mode*>& chain) const {
  SetOptionalParameterDefaultValues();
  string usage = Substitute("$0 $1", BuildUsageString(chain), name());
  string xml;
  xml += "<action>";
  xml += Substitute("<name>$0</name>", name());
  xml += Substitute("<description>$0</description>",
                    EscapeForHtmlToString(description()));
  xml += Substitute("<extra_description>$0</extra_description>",
                    EscapeForHtmlToString(extra_description().value_or("")));
  for (const auto& r : args().required) {
    usage += Substitute(" &lt;$0&gt;", r.name);
    xml += "<argument>";
    xml += "<kind>required</kind>";
    xml += Substitute("<name>$0</name>", r.name);
    xml += Substitute("<description>$0</description>",
                      EscapeForHtmlToString(r.description));
    xml += "<type>string</type>";
    xml += "</argument>";
  }

  if (args().variadic) {
    const ActionArgsDescriptor::Arg& v = *args().variadic;
    usage += Substitute(" &lt;$0&gt;...", v.name);
    xml += "<argument>";
    xml += "<kind>variadic</kind>";
    xml += Substitute("<name>$0</name>", v.name);
    xml += Substitute("<description>$0</description>",
                      EscapeForHtmlToString(v.description));
    xml += "<type>string</type>";
    xml += "</argument>";
  }

  for (const auto& o : args().optional) {
    google::CommandLineFlagInfo gflag_info =
        google::GetCommandLineFlagInfoOrDie(o.name.c_str());

    if (o.description) {
      gflag_info.description = *o.description;
    }

    if (gflag_info.type == "bool") {
      if (gflag_info.default_value == "false") {
        usage += Substitute(" [-$0]", o.name);
      } else {
        usage += Substitute(" [-no$0]", o.name);
      }
    } else {
      string noun;
      string::size_type last_underscore_idx = o.name.rfind('_');
      if (last_underscore_idx != string::npos &&
          last_underscore_idx != o.name.size() - 1) {
        noun = o.name.substr(last_underscore_idx + 1);
      } else {
        noun = o.name;
      }
      usage += Substitute(" [-$0=&lt;$1&gt;]", o.name, noun);
    }

    xml += "<argument>";
    xml += "<kind>optional</kind>";
    xml += Substitute("<name>$0</name>", gflag_info.name);
    xml += Substitute("<description>$0</description>",
                      EscapeForHtmlToString(gflag_info.description));
    xml += Substitute("<type>$0</type>", gflag_info.type);
    xml += Substitute("<default_value>$0</default_value>",
                      EscapeForHtmlToString(gflag_info.default_value));
    xml += "</argument>";
  }
  xml += Substitute("<usage>$0</usage>", EscapeForHtmlToString(usage));
  xml += "</action>";
  return xml;
}

void Action::SetOptionalParameterDefaultValues() const {
  for (const auto& param : args_.optional) {
    if (param.default_value) {
      CHECK_NE("", google::SetCommandLineOptionWithMode(param.name.c_str(),
          param.default_value->c_str(),
          google::FlagSettingMode::SET_FLAGS_DEFAULT));
    }
  }
}

void AppendHardWrapped(StringPiece to_append,
                       int continuation_indent,
                       string* dst) {
  constexpr int kWrapColumns = 78;
  DCHECK_LT(continuation_indent, kWrapColumns);

  if (to_append.empty() && dst->empty()) return;

  // The string we're appending to might not be already at a newline.
  size_t last_line_length = dst->size();
  auto newline_pos = dst->rfind('\n');
  if (newline_pos != string::npos) {
    last_line_length = dst->size() - newline_pos;
  }
  vector<StringPiece> lines = strings::Split(to_append, "\n");
  for (const auto& line : lines) {
    // Iterate through the words deciding where to wrap.
    vector<StringPiece> words = strings::Split(line, " ");
    if (words.empty()) continue;
    for (const auto& word : words) {
      // If the next word won't fit on this line, break before we append it.
      if (last_line_length + word.size() > kWrapColumns) {
        dst->push_back('\n');
        for (int i = 0; i < continuation_indent; i++) {
          dst->push_back(' ');
        }
        last_line_length = continuation_indent;
      }
      word.AppendToString(dst);
      dst->push_back(' ');
      last_line_length += word.size() + 1;
    }
    // Remove the extra space that we added at the end.
    dst->resize(dst->size() - 1);
    dst->push_back('\n');
    last_line_length = continuation_indent;
  }
  // Remove the extra Enter key that we added at the end.
  dst->resize(dst->size() - 1);
}
} // namespace tools
} // namespace kudu
