/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed 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.
 */

#ifndef ART_CMDLINE_DETAIL_CMDLINE_PARSE_ARGUMENT_DETAIL_H_
#define ART_CMDLINE_DETAIL_CMDLINE_PARSE_ARGUMENT_DETAIL_H_

#include <assert.h>
#include <algorithm>
#include <functional>
#include <memory>
#include <numeric>
#include <string_view>
#include <type_traits>
#include <vector>

#include "android-base/strings.h"

#include "base/indenter.h"
#include "cmdline_parse_result.h"
#include "cmdline_types.h"
#include "token_range.h"
#include "unit.h"

namespace art {
// Implementation details for the parser. Do not look inside if you hate templates.
namespace detail {

// A non-templated base class for argument parsers. Used by the general parser
// to parse arguments, without needing to know the argument type at compile time.
//
// This is an application of the type erasure idiom.
struct CmdlineParseArgumentAny {
  virtual ~CmdlineParseArgumentAny() {}

  // Attempt to parse this argument starting at arguments[position].
  // If the parsing succeeds, the parsed value will be saved as a side-effect.
  //
  // In most situations, the parsing will not match by returning kUnknown. In this case,
  // no tokens were consumed and the position variable will not be updated.
  //
  // At other times, parsing may fail due to validation but the initial token was still matched
  // (for example an out of range value, or passing in a string where an int was expected).
  // In this case the tokens are still consumed, and the position variable will get incremented
  // by all the consumed tokens.
  //
  // The # of tokens consumed by the parse attempt will be set as an out-parameter into
  // consumed_tokens. The parser should skip this many tokens before parsing the next
  // argument.
  virtual CmdlineResult ParseArgument(const TokenRange& arguments, size_t* consumed_tokens) = 0;
  // How many tokens should be taken off argv for parsing this argument.
  // For example "--help" is just 1, "-compiler-option _" would be 2 (since there's a space).
  //
  // A [min,max] range is returned to represent argument definitions with multiple
  // value tokens. (e.g. {"-h", "-h " } would return [1,2]).
  virtual std::pair<size_t, size_t> GetNumTokens() const = 0;
  // Get the run-time typename of the argument type.
  virtual const char* GetTypeName() const = 0;
  // Try to do a close match, returning how many tokens were matched against this argument
  // definition. More tokens is better.
  //
  // Do a quick match token-by-token, and see if they match.
  // Any tokens with a wildcard in them are only matched up until the wildcard.
  // If this is true, then the wildcard matching later on can still fail, so this is not
  // a guarantee that the argument is correct, it's more of a strong hint that the
  // user-provided input *probably* was trying to match this argument.
  //
  // Returns how many tokens were either matched (or ignored because there was a
  // wildcard present). 0 means no match. If the Size() tokens are returned.
  virtual size_t MaybeMatches(const TokenRange& tokens) = 0;

  virtual void DumpHelp(VariableIndentationOutputStream& os) = 0;

  virtual const std::optional<const char*>& GetCategory() = 0;
};

template <typename T>
using EnableIfNumeric = std::enable_if<std::is_arithmetic<T>::value>;

template <typename T>
using DisableIfNumeric = std::enable_if<!std::is_arithmetic<T>::value>;

// Argument definition information, created by an ArgumentBuilder and an UntypedArgumentBuilder.
template <typename TArg>
struct CmdlineParserArgumentInfo {
  // This version will only be used if TArg is arithmetic and thus has the <= operators.
  template <typename T = TArg>  // Necessary to get SFINAE to kick in.
  bool CheckRange(const TArg& value, typename EnableIfNumeric<T>::type* = nullptr) {
    if (has_range_) {
      return min_ <= value && value <= max_;
    }
    return true;
  }

  // This version will be used at other times when TArg is not arithmetic.
  template <typename T = TArg>
  bool CheckRange(const TArg&, typename DisableIfNumeric<T>::type* = nullptr) {
    assert(!has_range_);
    return true;
  }

  // Do a quick match token-by-token, and see if they match.
  // Any tokens with a wildcard in them only match the prefix up until the wildcard.
  //
  // If this is true, then the wildcard matching later on can still fail, so this is not
  // a guarantee that the argument is correct, it's more of a strong hint that the
  // user-provided input *probably* was trying to match this argument.
  size_t MaybeMatches(const TokenRange& token_list) const {
    auto best_match = FindClosestMatch(token_list);

    return best_match.second;
  }

  // Attempt to find the closest match (see MaybeMatches).
  //
  // Returns the token range that was the closest match and the # of tokens that
  // this range was matched up until.
  std::pair<const TokenRange*, size_t> FindClosestMatch(const TokenRange& token_list) const {
    const TokenRange* best_match_ptr = nullptr;

    size_t best_match = 0;
    for (auto&& token_range : tokenized_names_) {
      size_t this_match = token_range.MaybeMatches(token_list, std::string("_"));

      if (this_match > best_match) {
        best_match_ptr = &token_range;
        best_match = this_match;
      }
    }

    return std::make_pair(best_match_ptr, best_match);
  }

  template <typename T = TArg>  // Necessary to get SFINAE to kick in.
  void DumpHelp(VariableIndentationOutputStream& vios) {
    // Separate arguments
    vios.Stream() << std::endl;
    for (auto cname : names_) {
      std::string_view name = cname;
      if (using_blanks_) {
        name = name.substr(0, name.find('_'));
      }
      auto& os = vios.Stream();
      auto print_once = [&]() {
        os << name;
        if (using_blanks_) {
          if (has_value_map_) {
            bool first = true;
            for (auto [val, unused] : value_map_) {
              os << (first ? "{" : "|") << val;
              first = false;
            }
            os << "}";
          } else if (metavar_.has_value()) {
            os << *metavar_;
          } else {
            os << "{" << CmdlineType<T>::DescribeType() << "}";
          }
        }
      };
      print_once();
      if (appending_values_) {
        os << " [";
        print_once();
        os << "...]";
      }
      os << std::endl;
    }
    if (help_.has_value()) {
      ScopedIndentation si(&vios);
      vios.Stream() << *help_ << std::endl;
    }
  }


  // Mark the argument definition as completed, do not mutate the object anymore after this
  // call is done.
  //
  // Performs several checks of the validity and token calculations.
  void CompleteArgument() {
    assert(names_.size() >= 1);
    assert(!is_completed_);

    is_completed_ = true;

    size_t blank_count = 0;
    size_t token_count = 0;

    size_t global_blank_count = 0;
    size_t global_token_count = 0;
    for (auto&& name : names_) {
      std::string s(name);

      size_t local_blank_count = std::count(s.begin(), s.end(), '_');
      size_t local_token_count = std::count(s.begin(), s.end(), ' ');

      if (global_blank_count != 0) {
        assert(local_blank_count == global_blank_count
               && "Every argument descriptor string must have same amount of blanks (_)");
      }

      if (local_blank_count != 0) {
        global_blank_count = local_blank_count;
        blank_count++;

        assert(local_blank_count == 1 && "More than one blank is not supported");
        assert(s.back() == '_' && "The blank character must only be at the end of the string");
      }

      if (global_token_count != 0) {
        assert(local_token_count == global_token_count
               && "Every argument descriptor string must have same amount of tokens (spaces)");
      }

      if (local_token_count != 0) {
        global_token_count = local_token_count;
        token_count++;
      }

      // Tokenize every name, turning it from a string to a token list.
      tokenized_names_.clear();
      for (auto&& name1 : names_) {
        // Split along ' ' only, removing any duplicated spaces.
        tokenized_names_.push_back(
            TokenRange::Split(name1, {' '}).RemoveToken(" "));
      }

      // remove the _ character from each of the token ranges
      // we will often end up with an empty token (i.e. ["-XX", "_"] -> ["-XX", ""]
      // and this is OK because we still need an empty token to simplify
      // range comparisons
      simple_names_.clear();

      for (auto&& tokenized_name : tokenized_names_) {
        simple_names_.push_back(tokenized_name.RemoveCharacter('_'));
      }
    }

    if (token_count != 0) {
      assert(("Every argument descriptor string must have equal amount of tokens (spaces)" &&
          token_count == names_.size()));
    }

    if (blank_count != 0) {
      assert(("Every argument descriptor string must have an equal amount of blanks (_)" &&
          blank_count == names_.size()));
    }

    using_blanks_ = blank_count > 0;
    {
      size_t smallest_name_token_range_size =
          std::accumulate(tokenized_names_.begin(), tokenized_names_.end(), ~(0u),
                          [](size_t min, const TokenRange& cur) {
                            return std::min(min, cur.Size());
                          });
      size_t largest_name_token_range_size =
          std::accumulate(tokenized_names_.begin(), tokenized_names_.end(), 0u,
                          [](size_t max, const TokenRange& cur) {
                            return std::max(max, cur.Size());
                          });

      token_range_size_ = std::make_pair(smallest_name_token_range_size,
                                         largest_name_token_range_size);
    }

    if (has_value_list_) {
      assert(names_.size() == value_list_.size()
             && "Number of arg descriptors must match number of values");
      assert(!has_value_map_);
    }
    if (has_value_map_) {
      if (!using_blanks_) {
        assert(names_.size() == value_map_.size() &&
               "Since no blanks were specified, each arg is mapped directly into a mapped "
               "value without parsing; sizes must match");
      }

      assert(!has_value_list_);
    }

    if (!using_blanks_ && !CmdlineType<TArg>::kCanParseBlankless) {
      assert((has_value_map_ || has_value_list_) &&
             "Arguments without a blank (_) must provide either a value map or a value list");
    }

    TypedCheck();
  }

  // List of aliases for a single argument definition, e.g. {"-Xdex2oat", "-Xnodex2oat"}.
  std::vector<const char*> names_;
  // Is there at least 1 wildcard '_' in the argument definition?
  bool using_blanks_ = false;
  // [min, max] token counts in each arg def
  std::pair<size_t, size_t> token_range_size_;

  // contains all the names in a tokenized form, i.e. as a space-delimited list
  std::vector<TokenRange> tokenized_names_;

  // contains the tokenized names, but with the _ character stripped
  std::vector<TokenRange> simple_names_;

  // For argument definitions created with '.AppendValues()'
  // Meaning that parsing should mutate the existing value in-place if possible.
  bool appending_values_ = false;

  // For argument definitions created with '.WithRange(min, max)'
  bool has_range_ = false;
  TArg min_;
  TArg max_;

  // For argument definitions created with '.WithValueMap'
  bool has_value_map_ = false;
  std::vector<std::pair<const char*, TArg>> value_map_;

  // For argument definitions created with '.WithValues'
  bool has_value_list_ = false;
  std::vector<TArg> value_list_;

  std::optional<const char*> help_;
  std::optional<const char*> category_;
  std::optional<const char*> metavar_;

  // Make sure there's a default constructor.
  CmdlineParserArgumentInfo() = default;

  // Ensure there's a default move constructor.
  CmdlineParserArgumentInfo(CmdlineParserArgumentInfo&&) noexcept = default;

 private:
  // Perform type-specific checks at runtime.
  template <typename T = TArg>
  void TypedCheck(typename std::enable_if<std::is_same<Unit, T>::value>::type* = 0) {
    assert(!using_blanks_ &&
           "Blanks are not supported in Unit arguments; since a Unit has no parse-able value");
  }

  void TypedCheck() {}

  bool is_completed_ = false;
};

// A virtual-implementation of the necessary argument information in order to
// be able to parse arguments.
template <typename TArg>
struct CmdlineParseArgument : CmdlineParseArgumentAny {
  CmdlineParseArgument(CmdlineParserArgumentInfo<TArg>&& argument_info,
                       std::function<void(TArg&)>&& save_argument,
                       std::function<TArg&(void)>&& load_argument)
      : argument_info_(std::forward<decltype(argument_info)>(argument_info)),
        save_argument_(std::forward<decltype(save_argument)>(save_argument)),
        load_argument_(std::forward<decltype(load_argument)>(load_argument)) {
  }

  using UserTypeInfo = CmdlineType<TArg>;

  virtual CmdlineResult ParseArgument(const TokenRange& arguments, size_t* consumed_tokens) {
    assert(arguments.Size() > 0);
    assert(consumed_tokens != nullptr);

    auto closest_match_res = argument_info_.FindClosestMatch(arguments);
    size_t best_match_size = closest_match_res.second;
    const TokenRange* best_match_arg_def = closest_match_res.first;

    if (best_match_size > arguments.Size()) {
      // The best match has more tokens than were provided.
      // Shouldn't happen in practice since the outer parser does this check.
      return CmdlineResult(CmdlineResult::kUnknown, "Size mismatch");
    }

    assert(best_match_arg_def != nullptr);
    *consumed_tokens = best_match_arg_def->Size();

    if (!argument_info_.using_blanks_) {
      return ParseArgumentSingle(arguments.Join(' '));
    }

    // Extract out the blank value from arguments
    // e.g. for a def of "foo:_" and input "foo:bar", blank_value == "bar"
    std::string blank_value = "";
    size_t idx = 0;
    for (auto&& def_token : *best_match_arg_def) {
      auto&& arg_token = arguments[idx];

      // Does this definition-token have a wildcard in it?
      if (def_token.find('_') == std::string::npos) {
        // No, regular token. Match 1:1 against the argument token.
        bool token_match = def_token == arg_token;

        if (!token_match) {
          return CmdlineResult(CmdlineResult::kFailure,
                               std::string("Failed to parse ") + best_match_arg_def->GetToken(0)
                               + " at token " + std::to_string(idx));
        }
      } else {
        // This is a wild-carded token.
        TokenRange def_split_wildcards = TokenRange::Split(def_token, {'_'});

        // Extract the wildcard contents out of the user-provided arg_token.
        std::unique_ptr<TokenRange> arg_matches =
            def_split_wildcards.MatchSubstrings(arg_token, "_");
        if (arg_matches == nullptr) {
          return CmdlineResult(CmdlineResult::kFailure,
                               std::string("Failed to parse ") + best_match_arg_def->GetToken(0)
                               + ", with a wildcard pattern " + def_token
                               + " at token " + std::to_string(idx));
        }

        // Get the corresponding wildcard tokens from arg_matches,
        // and concatenate it to blank_value.
        for (size_t sub_idx = 0;
            sub_idx < def_split_wildcards.Size() && sub_idx < arg_matches->Size(); ++sub_idx) {
          if (def_split_wildcards[sub_idx] == "_") {
            blank_value += arg_matches->GetToken(sub_idx);
          }
        }
      }

      ++idx;
    }

    return ParseArgumentSingle(blank_value);
  }

  virtual void DumpHelp(VariableIndentationOutputStream& os) {
    argument_info_.DumpHelp(os);
  }

  virtual const std::optional<const char*>& GetCategory() {
    return argument_info_.category_;
  }

 private:
  virtual CmdlineResult ParseArgumentSingle(const std::string& argument) {
    // TODO: refactor to use LookupValue for the value lists/maps

    // Handle the 'WithValueMap(...)' argument definition
    if (argument_info_.has_value_map_) {
      for (auto&& value_pair : argument_info_.value_map_) {
        const char* name = value_pair.first;

        if (argument == name) {
          return SaveArgument(value_pair.second);
        }
      }

      // Error case: Fail, telling the user what the allowed values were.
      std::vector<std::string> allowed_values;
      for (auto&& value_pair : argument_info_.value_map_) {
        const char* name = value_pair.first;
        allowed_values.push_back(name);
      }

      std::string allowed_values_flat = android::base::Join(allowed_values, ',');
      return CmdlineResult(CmdlineResult::kFailure,
                           "Argument value '" + argument + "' does not match any of known valid "
                            "values: {" + allowed_values_flat + "}");
    }

    // Handle the 'WithValues(...)' argument definition
    if (argument_info_.has_value_list_) {
      size_t arg_def_idx = 0;
      for (auto&& value : argument_info_.value_list_) {
        auto&& arg_def_token = argument_info_.names_[arg_def_idx];

        if (arg_def_token == argument) {
          return SaveArgument(value);
        }
        ++arg_def_idx;
      }

      assert(arg_def_idx + 1 == argument_info_.value_list_.size() &&
             "Number of named argument definitions must match number of values defined");

      // Error case: Fail, telling the user what the allowed values were.
      std::vector<std::string> allowed_values;
      allowed_values.reserve(argument_info_.names_.size());
      for (auto&& arg_name : argument_info_.names_) {
        allowed_values.push_back(arg_name);
      }

      std::string allowed_values_flat = android::base::Join(allowed_values, ',');
      return CmdlineResult(CmdlineResult::kFailure,
                           "Argument value '" + argument + "' does not match any of known valid"
                            "values: {" + allowed_values_flat + "}");
    }

    // Handle the regular case where we parsed an unknown value from a blank.
    UserTypeInfo type_parser;

    if (argument_info_.appending_values_) {
      TArg& existing = load_argument_();
      CmdlineParseResult<TArg> result = type_parser.ParseAndAppend(argument, existing);

      assert(!argument_info_.has_range_);

      return std::move(result);
    }

    CmdlineParseResult<TArg> result = type_parser.Parse(argument);

    if (result.IsSuccess()) {
      TArg& value = result.GetValue();

      // Do a range check for 'WithRange(min,max)' argument definition.
      if (!argument_info_.CheckRange(value)) {
        return CmdlineParseResult<TArg>::OutOfRange(
            value, argument_info_.min_, argument_info_.max_);
      }

      return SaveArgument(value);
    }

    // Some kind of type-specific parse error. Pass the result as-is.
    CmdlineResult raw_result = std::move(result);
    return raw_result;
  }

 public:
  virtual const char* GetTypeName() const {
    // TODO: Obviate the need for each type specialization to hardcode the type name
    return UserTypeInfo::Name();
  }

  // How many tokens should be taken off argv for parsing this argument.
  // For example "--help" is just 1, "-compiler-option _" would be 2 (since there's a space).
  //
  // A [min,max] range is returned to represent argument definitions with multiple
  // value tokens. (e.g. {"-h", "-h " } would return [1,2]).
  virtual std::pair<size_t, size_t> GetNumTokens() const {
    return argument_info_.token_range_size_;
  }

  // See if this token range might begin the same as the argument definition.
  virtual size_t MaybeMatches(const TokenRange& tokens) {
    return argument_info_.MaybeMatches(tokens);
  }

 private:
  CmdlineResult SaveArgument(const TArg& value) {
    assert(!argument_info_.appending_values_
           && "If the values are being appended, then the updated parse value is "
               "updated by-ref as a side effect and shouldn't be stored directly");
    TArg val = value;
    save_argument_(val);
    return CmdlineResult(CmdlineResult::kSuccess);
  }

  CmdlineParserArgumentInfo<TArg> argument_info_;
  std::function<void(TArg&)> save_argument_;
  std::function<TArg&(void)> load_argument_;
};
}  // namespace detail  // NOLINT [readability/namespace] [5]
}  // namespace art

#endif  // ART_CMDLINE_DETAIL_CMDLINE_PARSE_ARGUMENT_DETAIL_H_
