/*
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
 *
 * (Taken from JGit org.eclipse.jgit.pgm.opt.CmdLineParser.)
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Git Development Community nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.google.gerrit.util.cli;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.util.cli.Localizable.localizable;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.flogger.FluentLogger;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.IllegalAnnotationError;
import org.kohsuke.args4j.NamedOptionDef;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.ParserProperties;
import org.kohsuke.args4j.spi.BooleanOptionHandler;
import org.kohsuke.args4j.spi.EnumOptionHandler;
import org.kohsuke.args4j.spi.MethodSetter;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Setter;
import org.kohsuke.args4j.spi.Setters;

/**
 * Extended command line parser which handles --foo=value arguments.
 *
 * <p>The args4j package does not natively handle --foo=value and instead prefers to see --foo value
 * on the command line. Many users are used to the GNU style --foo=value long option, so we convert
 * from the GNU style format to the args4j style format prior to invoking args4j for parsing.
 */
public class CmdLineParser {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public interface Factory {
    CmdLineParser create(Object bean);
  }

  /**
   * This may be used by an option handler during parsing to "call" additional parameters simulating
   * as if they had been passed from the command line originally.
   *
   * <p>To call additional parameters from within an option handler, instantiate this class with the
   * parameters and then call callParameters() with the additional parameters to be parsed.
   * OptionHandlers may optionally pass this class to other methods which may then both
   * parse/consume more parameters and call additional parameters.
   */
  public static class Parameters implements org.kohsuke.args4j.spi.Parameters {
    protected final String[] args;
    protected MyParser parser;
    protected int consumed = 0;

    public Parameters(org.kohsuke.args4j.spi.Parameters args, MyParser parser)
        throws CmdLineException {
      this.args = new String[args.size()];
      for (int i = 0; i < args.size(); i++) {
        this.args[i] = args.getParameter(i);
      }
      this.parser = parser;
    }

    public Parameters(String[] args, MyParser parser) {
      this.args = args;
      this.parser = parser;
    }

    @Override
    public String getParameter(int idx) throws CmdLineException {
      return args[idx];
    }

    /**
     * get and consume (consider parsed) a parameter
     *
     * @return the consumed parameter
     */
    public String consumeParameter() throws CmdLineException {
      return getParameter(consumed++);
    }

    @Override
    public int size() {
      return args.length;
    }

    /**
     * Add 'count' to the value of parsed parameters. May be called more than once.
     *
     * @param count How many parameters were just parsed.
     */
    public void consume(int count) {
      consumed += count;
    }

    /**
     * Reports handlers how many parameters were parsed
     *
     * @return the count of parsed parameters
     */
    public int getConsumed() {
      return consumed;
    }

    /**
     * Use during parsing to call additional parameters simulating as if they had been passed from
     * the command line originally.
     *
     * @param args A variable amount of parameters to call immediately
     *     <p>The parameters will be parsed immediately, before the remaining parameter will be
     *     parsed.
     *     <p>Note: Since this is done outside of the arg4j parsing loop, it will not match exactly
     *     what would happen if they were actually passed from the command line, but it will be
     *     pretty close. If this were moved to args4j, the interface could be the same and it could
     *     match exactly the behavior as if passed from the command line originally.
     */
    public void callParameters(String... args) throws CmdLineException {
      Parameters impl = new Parameters(Arrays.copyOfRange(args, 1, args.length), parser);
      parser.findOptionByName(args[0]).parseArguments(impl);
    }
  }

  private final OptionHandlers handlers;
  private final MyParser parser;

  @SuppressWarnings("rawtypes")
  private Map<String, OptionHandler> options;

  /**
   * Creates a new command line owner that parses arguments/options and set them into the given
   * object.
   *
   * @param bean instance of a class annotated by {@link org.kohsuke.args4j.Option} and {@link
   *     org.kohsuke.args4j.Argument}. this object will receive values.
   * @throws IllegalAnnotationError if the option bean class is using args4j annotations
   *     incorrectly.
   */
  @Inject
  public CmdLineParser(OptionHandlers handlers, @Assisted final Object bean)
      throws IllegalAnnotationError {
    this.handlers = handlers;
    this.parser = new MyParser(bean);
  }

  public void addArgument(Setter<?> setter, Argument a) {
    parser.addArgument(setter, a);
  }

  public void addOption(Setter<?> setter, Option o) {
    parser.addOption(setter, o);
  }

  public void printSingleLineUsage(Writer w, ResourceBundle rb) {
    parser.printSingleLineUsage(w, rb);
  }

  public void printUsage(Writer out, ResourceBundle rb) {
    parser.printUsage(out, rb);
  }

  public void printDetailedUsage(String name, StringWriter out) {
    out.write(name);
    printSingleLineUsage(out, null);
    out.write('\n');
    out.write('\n');
    printUsage(out, null);
    out.write('\n');
  }

  public void printQueryStringUsage(String name, StringWriter out) {
    out.write(name);

    char next = '?';
    List<NamedOptionDef> booleans = new ArrayList<>();
    for (@SuppressWarnings("rawtypes") OptionHandler handler : parser.optionsList) {
      if (handler.option instanceof NamedOptionDef) {
        NamedOptionDef n = (NamedOptionDef) handler.option;

        if (handler instanceof BooleanOptionHandler) {
          booleans.add(n);
          continue;
        }

        if (!n.required()) {
          out.write('[');
        }
        out.write(next);
        next = '&';
        if (n.name().startsWith("--")) {
          out.write(n.name().substring(2));
        } else if (n.name().startsWith("-")) {
          out.write(n.name().substring(1));
        } else {
          out.write(n.name());
        }
        out.write('=');

        out.write(metaVar(handler, n));
        if (!n.required()) {
          out.write(']');
        }
        if (n.isMultiValued()) {
          out.write('*');
        }
      }
    }
    for (NamedOptionDef n : booleans) {
      if (!n.required()) {
        out.write('[');
      }
      out.write(next);
      next = '&';
      if (n.name().startsWith("--")) {
        out.write(n.name().substring(2));
      } else if (n.name().startsWith("-")) {
        out.write(n.name().substring(1));
      } else {
        out.write(n.name());
      }
      if (!n.required()) {
        out.write(']');
      }
    }
  }

  private static String metaVar(OptionHandler<?> handler, NamedOptionDef n) {
    String var = n.metaVar();
    if (Strings.isNullOrEmpty(var)) {
      var = handler.getDefaultMetaVariable();
      if (handler instanceof EnumOptionHandler) {
        var = var.substring(1, var.length() - 1).replace(" ", "");
      }
    }
    return var;
  }

  public boolean wasHelpRequestedByOption() {
    return parser.help;
  }

  public void parseArgument(String... args) throws CmdLineException {
    List<String> tmp = Lists.newArrayListWithCapacity(args.length);
    for (int argi = 0; argi < args.length; argi++) {
      final String str = args[argi];
      if (str.equals("--")) {
        while (argi < args.length) {
          tmp.add(args[argi++]);
        }
        break;
      }

      if (str.startsWith("--")) {
        final int eq = str.indexOf('=');
        if (eq > 0) {
          tmp.add(str.substring(0, eq));
          tmp.add(str.substring(eq + 1));
          continue;
        }
      }

      tmp.add(str);
    }
    parser.parseArgument(tmp.toArray(new String[tmp.size()]));
  }

  public void parseOptionMap(ListMultimap<String, String> params) throws CmdLineException {
    logger.atFinest().log("Command-line parameters: %s", params.keySet());
    List<String> tmp = Lists.newArrayListWithCapacity(2 * params.size());
    for (String key : params.keySet()) {
      String name = makeOption(key);

      if (isBooleanOption(name)) {
        boolean on = false;
        for (String value : params.get(key)) {
          on = toBoolean(key, value);
        }
        if (on) {
          tmp.add(name);
        }
      } else {
        for (String value : params.get(key)) {
          tmp.add(name);
          tmp.add(value);
        }
      }
    }
    parser.parseArgument(tmp.toArray(new String[tmp.size()]));
  }

  public void parseWithPrefix(String prefix, Object bean) {
    parser.parseWithPrefix(prefix, bean);
  }

  public void drainOptionQueue() {
    parser.addOptionsWithMetRequirements();
  }

  private boolean isBooleanOption(String name) {
    return findHandler(makeOption(name)) instanceof BooleanOptionHandler;
  }

  private String makeOption(String name) {
    if (!name.startsWith("-")) {
      if (name.length() == 1) {
        name = "-" + name;
      } else {
        name = "--" + name;
      }
    }
    return name;
  }

  @SuppressWarnings("rawtypes")
  private OptionHandler findHandler(String name) {
    if (options == null) {
      options = index(parser.optionsList);
    }
    return options.get(name);
  }

  @SuppressWarnings("rawtypes")
  private static Map<String, OptionHandler> index(List<OptionHandler> in) {
    Map<String, OptionHandler> m = new HashMap<>();
    for (OptionHandler handler : in) {
      if (handler.option instanceof NamedOptionDef) {
        NamedOptionDef def = (NamedOptionDef) handler.option;
        if (!def.isArgument()) {
          m.put(def.name(), handler);
          for (String alias : def.aliases()) {
            m.put(alias, handler);
          }
        }
      }
    }
    return m;
  }

  private boolean toBoolean(String name, String value) throws CmdLineException {
    if ("true".equals(value)
        || "t".equals(value)
        || "yes".equals(value)
        || "y".equals(value)
        || "on".equals(value)
        || "1".equals(value)
        || value == null
        || "".equals(value)) {
      return true;
    }

    if ("false".equals(value)
        || "f".equals(value)
        || "no".equals(value)
        || "n".equals(value)
        || "off".equals(value)
        || "0".equals(value)) {
      return false;
    }

    throw new CmdLineException(parser, localizable("invalid boolean \"%s=%s\""), name, value);
  }

  private static Option newPrefixedOption(String prefix, Option o) {
    requireNonNull(prefix);
    checkArgument(o.name().startsWith("-"), "Option name must start with '-': %s", o);
    ImmutableList<String> aliases =
        Arrays.stream(o.aliases()).map(prefix::concat).collect(toImmutableList());
    return OptionUtil.newOption(
        prefix + o.name(),
        aliases,
        o.usage(),
        o.metaVar(),
        o.required(),
        false,
        o.hidden(),
        o.handler(),
        ImmutableList.copyOf(o.depends()),
        ImmutableList.of());
  }

  public class MyParser extends org.kohsuke.args4j.CmdLineParser {
    boolean help;

    @SuppressWarnings("rawtypes")
    private List<OptionHandler> optionsList;

    private Map<String, QueuedOption> queuedOptionsByName = new LinkedHashMap<>();

    private class QueuedOption {
      public final Option option;

      @SuppressWarnings("rawtypes")
      public final Setter setter;

      public final String[] requiredOptions;

      private QueuedOption(
          Option option,
          @SuppressWarnings("rawtypes") Setter setter,
          RequiresOptions requiresOptions) {
        this.option = option;
        this.setter = setter;
        this.requiredOptions = requiresOptions != null ? requiresOptions.value() : new String[0];
      }
    }

    MyParser(Object bean) {
      super(bean, ParserProperties.defaults().withAtSyntax(false));
      parseAdditionalOptions(bean, new HashSet<>());
      addOptionsWithMetRequirements();
      ensureOptionsInitialized();
    }

    public int addOptionsWithMetRequirements() {
      int count = 0;
      for (Iterator<Map.Entry<String, QueuedOption>> it = queuedOptionsByName.entrySet().iterator();
          it.hasNext(); ) {
        QueuedOption queuedOption = it.next().getValue();
        if (hasAllRequiredOptions(queuedOption)) {
          addOption(queuedOption.setter, queuedOption.option);
          it.remove();
          count++;
        }
      }
      if (count > 0) {
        count += addOptionsWithMetRequirements();
      }
      return count;
    }

    private boolean hasAllRequiredOptions(QueuedOption queuedOption) {
      for (String name : queuedOption.requiredOptions) {
        if (findOptionByName(name) == null) {
          return false;
        }
      }
      return true;
    }

    // NOTE: Argument annotations on bean are ignored.
    public void parseWithPrefix(String prefix, Object bean) {
      parseWithPrefix(prefix, bean, new HashSet<>());
    }

    private void parseWithPrefix(String prefix, Object bean, Set<Object> parsedBeans) {
      if (!parsedBeans.add(bean)) {
        return;
      }
      // recursively process all the methods/fields.
      for (Class<?> c = bean.getClass(); c != null; c = c.getSuperclass()) {
        for (Method m : c.getDeclaredMethods()) {
          Option o = m.getAnnotation(Option.class);
          if (o != null) {
            queueOption(
                newPrefixedOption(prefix, o),
                new MethodSetter(this, bean, m),
                m.getAnnotation(RequiresOptions.class));
          }
        }
        for (Field f : c.getDeclaredFields()) {
          Option o = f.getAnnotation(Option.class);
          if (o != null) {
            queueOption(
                newPrefixedOption(prefix, o),
                Setters.create(f, bean),
                f.getAnnotation(RequiresOptions.class));
          }
          if (f.isAnnotationPresent(Options.class)) {
            try {
              parseWithPrefix(
                  prefix + f.getAnnotation(Options.class).prefix(), f.get(bean), parsedBeans);
            } catch (IllegalAccessException e) {
              throw new IllegalAnnotationError(e);
            }
          }
        }
      }
    }

    private void parseAdditionalOptions(Object bean, Set<Object> parsedBeans) {
      for (Class<?> c = bean.getClass(); c != null; c = c.getSuperclass()) {
        for (Field f : c.getDeclaredFields()) {
          if (f.isAnnotationPresent(Options.class)) {
            Object additionalBean;
            try {
              additionalBean = f.get(bean);
            } catch (IllegalAccessException e) {
              throw new IllegalAnnotationError(e);
            }
            parseWithPrefix(f.getAnnotation(Options.class).prefix(), additionalBean, parsedBeans);
          }
        }
      }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    protected OptionHandler createOptionHandler(OptionDef option, Setter setter) {
      if (isHandlerSpecified(option) || isEnum(setter) || isPrimitive(setter)) {
        return add(super.createOptionHandler(option, setter));
      }

      OptionHandlerFactory<?> factory = handlers.get(setter.getType());
      if (factory != null) {
        return factory.create(this, option, setter);
      }
      return add(super.createOptionHandler(option, setter));
    }

    /**
     * Finds a registered {@code OptionHandler} by its name or its alias.
     *
     * @param name name
     * @return the {@code OptionHandler} or {@code null}
     *     <p>Note: this is cut & pasted from the parent class in arg4j, it was private and it
     *     needed to be exposed.
     */
    @SuppressWarnings("rawtypes")
    public OptionHandler findOptionByName(String name) {
      for (OptionHandler h : optionsList) {
        NamedOptionDef option = (NamedOptionDef) h.option;
        if (name.equals(option.name())) {
          return h;
        }
        for (String alias : option.aliases()) {
          if (name.equals(alias)) {
            return h;
          }
        }
      }
      return null;
    }

    private void queueOption(
        Option option,
        @SuppressWarnings("rawtypes") Setter setter,
        RequiresOptions requiresOptions) {
      if (queuedOptionsByName.put(option.name(), new QueuedOption(option, setter, requiresOptions))
          != null) {
        throw new IllegalAnnotationError(
            "Option name " + option.name() + " is used more than once");
      }
    }

    @SuppressWarnings("rawtypes")
    private OptionHandler add(OptionHandler handler) {
      ensureOptionsInitialized();
      optionsList.add(handler);
      return handler;
    }

    private void ensureOptionsInitialized() {
      if (optionsList == null) {
        optionsList = new ArrayList<>();
        addOption(newHelpSetter(), newHelpOption());
      }
    }

    private Setter<?> newHelpSetter() {
      try {
        return Setters.create(getClass().getDeclaredField("help"), this);
      } catch (NoSuchFieldException e) {
        throw new IllegalStateException(e);
      }
    }

    private Option newHelpOption() {
      return OptionUtil.newOption(
          "--help",
          ImmutableList.of("-h"),
          "display this help text",
          "",
          false,
          false,
          false,
          BooleanOptionHandler.class,
          ImmutableList.of(),
          ImmutableList.of());
    }

    private boolean isHandlerSpecified(OptionDef option) {
      return option.handler() != OptionHandler.class;
    }

    private <T> boolean isEnum(Setter<T> setter) {
      return Enum.class.isAssignableFrom(setter.getType());
    }

    private <T> boolean isPrimitive(Setter<T> setter) {
      return setter.getType().isPrimitive();
    }
  }

  public CmdLineException reject(String message) {
    return new CmdLineException(parser, localizable(message));
  }
}
