#ifndef SRC_NODE_OPTIONS_INL_H_
#define SRC_NODE_OPTIONS_INL_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include <cstdlib>
#include "node_options.h"
#include "util.h"

namespace node {

PerIsolateOptions* PerProcessOptions::get_per_isolate_options() {
  return per_isolate.get();
}

EnvironmentOptions* PerIsolateOptions::get_per_env_options() {
  return per_env.get();
}

namespace options_parser {

template <typename Options>
void OptionsParser<Options>::AddOption(const char* name,
                                       const char* help_text,
                                       bool Options::* field,
                                       OptionEnvvarSettings env_setting) {
  options_.emplace(name,
                   OptionInfo{kBoolean,
                              std::make_shared<SimpleOptionField<bool>>(field),
                              env_setting,
                              help_text});
}

template <typename Options>
void OptionsParser<Options>::AddOption(const char* name,
                                       const char* help_text,
                                       uint64_t Options::* field,
                                       OptionEnvvarSettings env_setting) {
  options_.emplace(
      name,
      OptionInfo{kUInteger,
                 std::make_shared<SimpleOptionField<uint64_t>>(field),
                 env_setting,
                 help_text});
}

template <typename Options>
void OptionsParser<Options>::AddOption(const char* name,
                                       const char* help_text,
                                       int64_t Options::* field,
                                       OptionEnvvarSettings env_setting) {
  options_.emplace(
      name,
      OptionInfo{kInteger,
                 std::make_shared<SimpleOptionField<int64_t>>(field),
                 env_setting,
                 help_text});
}

template <typename Options>
void OptionsParser<Options>::AddOption(const char* name,
                                       const char* help_text,
                                       std::string Options::* field,
                                       OptionEnvvarSettings env_setting) {
  options_.emplace(
      name,
      OptionInfo{kString,
                 std::make_shared<SimpleOptionField<std::string>>(field),
                 env_setting,
                 help_text});
}

template <typename Options>
void OptionsParser<Options>::AddOption(
    const char* name,
    const char* help_text,
    std::vector<std::string> Options::* field,
    OptionEnvvarSettings env_setting) {
  options_.emplace(name, OptionInfo {
    kStringList,
    std::make_shared<SimpleOptionField<std::vector<std::string>>>(field),
    env_setting,
    help_text
  });
}

template <typename Options>
void OptionsParser<Options>::AddOption(const char* name,
                                       const char* help_text,
                                       HostPort Options::* field,
                                       OptionEnvvarSettings env_setting) {
  options_.emplace(
      name,
      OptionInfo{kHostPort,
                 std::make_shared<SimpleOptionField<HostPort>>(field),
                 env_setting,
                 help_text});
}

template <typename Options>
void OptionsParser<Options>::AddOption(const char* name,
                                       const char* help_text,
                                       NoOp no_op_tag,
                                       OptionEnvvarSettings env_setting) {
  options_.emplace(name, OptionInfo{kNoOp, nullptr, env_setting, help_text});
}

template <typename Options>
void OptionsParser<Options>::AddOption(const char* name,
                                       const char* help_text,
                                       V8Option v8_option_tag,
                                       OptionEnvvarSettings env_setting) {
  options_.emplace(name,
                   OptionInfo{kV8Option, nullptr, env_setting, help_text});
}

template <typename Options>
void OptionsParser<Options>::AddAlias(const char* from,
                                      const char* to) {
  aliases_[from] = { to };
}

template <typename Options>
void OptionsParser<Options>::AddAlias(const char* from,
                                      const std::vector<std::string>& to) {
  aliases_[from] = to;
}

template <typename Options>
void OptionsParser<Options>::AddAlias(
    const char* from,
    const std::initializer_list<std::string>& to) {
  AddAlias(from, std::vector<std::string>(to));
}

template <typename Options>
void OptionsParser<Options>::Implies(const char* from,
                                     const char* to) {
  auto it = options_.find(to);
  CHECK_NE(it, options_.end());
  CHECK_EQ(it->second.type, kBoolean);
  implications_.emplace(from, Implication {
    it->second.field, true
  });
}

template <typename Options>
void OptionsParser<Options>::ImpliesNot(const char* from,
                                        const char* to) {
  auto it = options_.find(to);
  CHECK_NE(it, options_.end());
  CHECK_EQ(it->second.type, kBoolean);
  implications_.emplace(from, Implication {
    it->second.field, false
  });
}

template <typename Options>
template <typename OriginalField, typename ChildOptions>
auto OptionsParser<Options>::Convert(
    std::shared_ptr<OriginalField> original,
    ChildOptions* (Options::* get_child)()) {
  // If we have a field on ChildOptions, and we want to access it from an
  // Options instance, we call get_child() on the original Options and then
  // access it, i.e. this class implements a kind of function chaining.
  struct AdaptedField : BaseOptionField {
    void* LookupImpl(Options* options) const override {
      return original->LookupImpl((options->*get_child)());
    }

    AdaptedField(
        std::shared_ptr<OriginalField> original,
        ChildOptions* (Options::* get_child)())
          : original(original), get_child(get_child) {}

    std::shared_ptr<OriginalField> original;
    ChildOptions* (Options::* get_child)();
  };

  return std::shared_ptr<BaseOptionField>(
      new AdaptedField(original, get_child));
}
template <typename Options>
template <typename ChildOptions>
auto OptionsParser<Options>::Convert(
    typename OptionsParser<ChildOptions>::OptionInfo original,
    ChildOptions* (Options::* get_child)()) {
  return OptionInfo{original.type,
                    Convert(original.field, get_child),
                    original.env_setting,
                    original.help_text};
}

template <typename Options>
template <typename ChildOptions>
auto OptionsParser<Options>::Convert(
    typename OptionsParser<ChildOptions>::Implication original,
    ChildOptions* (Options::* get_child)()) {
  return Implication {
    Convert(original.target_field, get_child),
    original.target_value
  };
}

template <typename Options>
template <typename ChildOptions>
void OptionsParser<Options>::Insert(
    const OptionsParser<ChildOptions>& child_options_parser,
    ChildOptions* (Options::* get_child)()) {
  aliases_.insert(std::begin(child_options_parser.aliases_),
                  std::end(child_options_parser.aliases_));

  for (const auto& pair : child_options_parser.options_)
    options_.emplace(pair.first, Convert(pair.second, get_child));

  for (const auto& pair : child_options_parser.implications_)
    implications_.emplace(pair.first, Convert(pair.second, get_child));
}

inline std::string NotAllowedInEnvErr(const std::string& arg) {
  return arg + " is not allowed in NODE_OPTIONS";
}

inline std::string RequiresArgumentErr(const std::string& arg) {
  return arg + " requires an argument";
}

// We store some of the basic information around a single Parse call inside
// this struct, to separate storage of command line arguments and their
// handling. In particular, this makes it easier to introduce 'synthetic'
// arguments that get inserted by expanding option aliases.
struct ArgsInfo {
  // Generally, the idea here is that the first entry in `*underlying` stores
  // the "0th" argument (the program name), then `synthetic_args` are inserted,
  // followed by the remainder of `*underlying`.
  std::vector<std::string>* underlying;
  std::vector<std::string> synthetic_args;

  std::vector<std::string>* exec_args;

  ArgsInfo(std::vector<std::string>* args,
           std::vector<std::string>* exec_args)
    : underlying(args), exec_args(exec_args) {}

  size_t remaining() const {
    // -1 to account for the program name.
    return underlying->size() - 1 + synthetic_args.size();
  }

  bool empty() const { return remaining() == 0; }
  const std::string& program_name() const { return underlying->at(0); }

  std::string& first() {
    return synthetic_args.empty() ? underlying->at(1) : synthetic_args.front();
  }

  std::string pop_first() {
    std::string ret = std::move(first());
    if (synthetic_args.empty()) {
      // Only push arguments to `exec_args` that were also originally passed
      // on the command line (i.e. not generated through alias expansion).
      // '--' is a special case here since its purpose is to end `exec_argv`,
      // which is why we do not include it.
      if (exec_args != nullptr && ret != "--")
        exec_args->push_back(ret);
      underlying->erase(underlying->begin() + 1);
    } else {
      synthetic_args.erase(synthetic_args.begin());
    }
    return ret;
  }
};

template <typename Options>
void OptionsParser<Options>::Parse(
    std::vector<std::string>* const orig_args,
    std::vector<std::string>* const exec_args,
    std::vector<std::string>* const v8_args,
    Options* const options,
    OptionEnvvarSettings required_env_settings,
    std::vector<std::string>* const errors) const {
  ArgsInfo args(orig_args, exec_args);

  // The first entry is the process name. Make sure it ends up in the V8 argv,
  // since V8::SetFlagsFromCommandLine() expects that to hold true for that
  // array as well.
  if (v8_args->empty())
    v8_args->push_back(args.program_name());

  while (!args.empty() && errors->empty()) {
    if (args.first().size() <= 1 || args.first()[0] != '-') break;

    // We know that we're either going to consume this
    // argument or fail completely.
    const std::string arg = args.pop_first();

    if (arg == "--") {
      if (required_env_settings == kAllowedInEnvironment)
        errors->push_back(NotAllowedInEnvErr("--"));
      break;
    }

    // Only allow --foo=bar notation for options starting with double dashes.
    // (E.g. -e=a is not allowed as shorthand for --eval=a, which would
    // otherwise be the result of alias expansion.)
    const std::string::size_type equals_index =
        arg[0] == '-' && arg[1] == '-' ? arg.find('=') : std::string::npos;
    std::string name =
      equals_index == std::string::npos ? arg : arg.substr(0, equals_index);

    // Store the 'original name' of the argument. This name differs from
    // 'name' in that it contains a possible '=' sign and is not affected
    // by alias expansion.
    std::string original_name = name;
    if (equals_index != std::string::npos)
      original_name += '=';

    // Normalize by replacing `_` with `-` in options.
    for (std::string::size_type i = 2; i < name.size(); ++i) {
      if (name[i] == '_')
        name[i] = '-';
    }

    {
      auto it = aliases_.end();
      // Expand aliases:
      // - If `name` can be found in `aliases_`.
      // - If `name` + '=' can be found in `aliases_`.
      // - If `name` + " <arg>" can be found in `aliases_`, and we have
      //   a subsequent argument that does not start with '-' itself.
      while ((it = aliases_.find(name)) != aliases_.end() ||
             (equals_index != std::string::npos &&
              (it = aliases_.find(name + '=')) != aliases_.end()) ||
             (!args.empty() &&
                 !args.first().empty() &&
                 args.first()[0] != '-' &&
              (it = aliases_.find(name + " <arg>")) != aliases_.end())) {
        const std::string prev_name = std::move(name);
        const std::vector<std::string>& expansion = it->second;

        // Use the first entry in the expansion as the new 'name'.
        name = expansion.front();

        if (expansion.size() > 1) {
          // The other arguments, if any, are going to be handled later.
          args.synthetic_args.insert(
              args.synthetic_args.begin(),
              expansion.begin() + 1,
              expansion.end());
        }

        if (name == prev_name) break;
      }
    }

    auto it = options_.find(name);

    if ((it == options_.end() ||
         it->second.env_setting == kDisallowedInEnvironment) &&
        required_env_settings == kAllowedInEnvironment) {
      errors->push_back(NotAllowedInEnvErr(original_name));
      break;
    }

    if (it == options_.end()) {
      v8_args->push_back(arg);
      continue;
    }

    {
      auto implications = implications_.equal_range(name);
      for (auto it = implications.first; it != implications.second; ++it) {
        *it->second.target_field->template Lookup<bool>(options) =
            it->second.target_value;
      }
    }

    const OptionInfo& info = it->second;
    std::string value;
    if (info.type != kBoolean && info.type != kNoOp && info.type != kV8Option) {
      if (equals_index != std::string::npos) {
        value = arg.substr(equals_index + 1);
        if (value.empty()) {
        missing_argument:
          errors->push_back(RequiresArgumentErr(original_name));
          break;
        }
      } else {
        if (args.empty())
          goto missing_argument;

        value = args.pop_first();

        if (!value.empty() && value[0] == '-') {
          goto missing_argument;
        } else {
          if (!value.empty() && value[0] == '\\' && value[1] == '-')
            value = value.substr(1);  // Treat \- as escaping an -.
        }
      }
    }

    switch (info.type) {
      case kBoolean:
        *Lookup<bool>(info.field, options) = true;
        break;
      case kInteger:
        *Lookup<int64_t>(info.field, options) = std::atoll(value.c_str());
        break;
      case kUInteger:
        *Lookup<uint64_t>(info.field, options) = std::stoull(value);
        break;
      case kString:
        *Lookup<std::string>(info.field, options) = value;
        break;
      case kStringList:
        Lookup<std::vector<std::string>>(info.field, options)
            ->emplace_back(std::move(value));
        break;
      case kHostPort:
        Lookup<HostPort>(info.field, options)
            ->Update(SplitHostPort(value, errors));
        break;
      case kNoOp:
        break;
      case kV8Option:
        v8_args->push_back(arg);
        break;
      default:
        UNREACHABLE();
    }
  }
  options->CheckOptions(errors);
}

}  // namespace options_parser
}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#endif  // SRC_NODE_OPTIONS_INL_H_
