// Copyright 2017 The Bazel Authors. All rights reserved.
//
// 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.

package com.google.devtools.common.options;

import static java.util.Arrays.stream;
import static java.util.Comparator.comparing;

import com.google.common.collect.ImmutableList;
import com.google.devtools.common.options.OptionsParser.ConstructionException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * Everything the {@link OptionsParser} needs to know about how an option is defined.
 *
 * <p>An {@code OptionDefinition} is effectively a wrapper around the {@link Option} annotation and
 * the {@link Field} that is annotated, and should contain all logic about default settings and
 * behavior.
 */
public class OptionDefinition implements Comparable<OptionDefinition> {

  /**
   * A special value used to specify an absence of default value.
   *
   * @see Option#defaultValue
   */
  public static final String SPECIAL_NULL_DEFAULT_VALUE = "null";

  // TODO(b/65049598) make ConstructionException checked, which will make this checked as well.
  static class NotAnOptionException extends ConstructionException {
    NotAnOptionException(Field field) {
      super(
          "The field "
              + field.getName()
              + " does not have the right annotation to be considered an option.");
    }
  }

  /**
   * If the {@code field} is annotated with the appropriate @{@link Option} annotation, returns the
   * {@code OptionDefinition} for that option. Otherwise, throws a {@link NotAnOptionException}.
   *
   * <p>These values are cached in the {@link OptionsData} layer and should be accessed through
   * {@link OptionsParser#getOptionDefinitions(Class)}.
   */
  static OptionDefinition extractOptionDefinition(Field field) {
    Option annotation = field == null ? null : field.getAnnotation(Option.class);
    if (annotation == null) {
      throw new NotAnOptionException(field);
    }
    return new OptionDefinition(field, annotation);
  }

  private final Field field;
  private final Option optionAnnotation;
  private Converter<?> converter = null;
  private Object defaultValue = null;

  private OptionDefinition(Field field, Option optionAnnotation) {
    this.field = field;
    this.optionAnnotation = optionAnnotation;
  }

  /** Returns the underlying {@code field} for this {@code OptionDefinition}. */
  public Field getField() {
    return field;
  }

  /**
   * Returns the name of the option ("--name").
   *
   * <p>Labelled "Option" name to distinguish it from the field's name.
   */
  public String getOptionName() {
    return optionAnnotation.name();
  }

  /** The single-character abbreviation of the option ("-a"). */
  public char getAbbreviation() {
    return optionAnnotation.abbrev();
  }

  /** {@link Option#help()} */
  public String getHelpText() {
    return optionAnnotation.help();
  }

  /** {@link Option#valueHelp()} */
  public String getValueTypeHelpText() {
    return optionAnnotation.valueHelp();
  }

  /** {@link Option#defaultValue()} */
  public String getUnparsedDefaultValue() {
    return optionAnnotation.defaultValue();
  }

  /** {@link Option#category()} */
  public String getOptionCategory() {
    return optionAnnotation.category();
  }

  /** {@link Option#documentationCategory()} */
  public OptionDocumentationCategory getDocumentationCategory() {
    return optionAnnotation.documentationCategory();
  }

  /** {@link Option#effectTags()} */
  public OptionEffectTag[] getOptionEffectTags() {
    return optionAnnotation.effectTags();
  }

  /** {@link Option#metadataTags()} */
  public OptionMetadataTag[] getOptionMetadataTags() {
    return optionAnnotation.metadataTags();
  }

  /** {@link Option#metadataTags()} */
  public boolean hasOptionMetadataTag(OptionMetadataTag tag) {
    return stream(getOptionMetadataTags()).anyMatch(tag::equals);
  }

  /** {@link Option#converter()} ()} */
  @SuppressWarnings({"rawtypes"})
  public Class<? extends Converter> getProvidedConverter() {
    return optionAnnotation.converter();
  }

  /** {@link Option#allowMultiple()} */
  public boolean allowsMultiple() {
    return optionAnnotation.allowMultiple();
  }

  /** {@link Option#expansion()} */
  public String[] getOptionExpansion() {
    return optionAnnotation.expansion();
  }

  /** {@link Option#implicitRequirements()} ()} */
  public String[] getImplicitRequirements() {
    return optionAnnotation.implicitRequirements();
  }

  /** {@link Option#deprecationWarning()} ()} */
  public String getDeprecationWarning() {
    return optionAnnotation.deprecationWarning();
  }

  /** {@link Option#oldName()} ()} ()} */
  public String getOldOptionName() {
    return optionAnnotation.oldName();
  }

  /** Returns whether an option --foo has a negative equivalent --nofoo. */
  public boolean hasNegativeOption() {
    return getType().equals(boolean.class) || getType().equals(TriState.class);
  }

  /** The type of the optionDefinition. */
  public Class<?> getType() {
    return field.getType();
  }

  /** Whether this field has type Void. */
  boolean isVoidField() {
    return getType().equals(Void.class);
  }

  public boolean isSpecialNullDefault() {
    return SPECIAL_NULL_DEFAULT_VALUE.equals(getUnparsedDefaultValue()) && !getType().isPrimitive();
  }

  /** Returns whether the arg is an expansion option. */
  public boolean isExpansionOption() {
    return getOptionExpansion().length > 0;
  }

  /** Returns whether the arg is an expansion option. */
  public boolean hasImplicitRequirements() {
    return (getImplicitRequirements().length > 0);
  }

  /**
   * For an option that does not use {@link Option#allowMultiple}, returns its type. For an option
   * that does use it, asserts that the type is a {@code List<T>} and returns its element type
   * {@code T}.
   */
  Type getFieldSingularType() {
    Type fieldType = getField().getGenericType();
    if (allowsMultiple()) {
      // The validity of the converter is checked at compile time. We know the type to be
      // List<singularType>.
      ParameterizedType pfieldType = (ParameterizedType) fieldType;
      fieldType = pfieldType.getActualTypeArguments()[0];
    }
    return fieldType;
  }

  /**
   * Retrieves the {@link Converter} that will be used for this option, taking into account the
   * default converters if an explicit one is not specified.
   *
   * <p>Memoizes the converter-finding logic to avoid repeating the computation.
   */
  public Converter<?> getConverter() {
    if (converter != null) {
      return converter;
    }
    Class<? extends Converter> converterClass = getProvidedConverter();
    if (converterClass == Converter.class) {
      // No converter provided, use the default one.
      Type type = getFieldSingularType();
      converter = Converters.DEFAULT_CONVERTERS.get(type);
    } else {
      try {
        // Instantiate the given Converter class.
        Constructor<?> constructor = converterClass.getConstructor();
        converter = (Converter<?>) constructor.newInstance();
      } catch (SecurityException | IllegalArgumentException | ReflectiveOperationException e) {
        // This indicates an error in the Converter, and should be discovered the first time it is
        // used.
        throw new ConstructionException(
            String.format("Error in the provided converter for option %s", getField().getName()),
            e);
      }
    }
    return converter;
  }

  /**
   * Returns whether a field should be considered as boolean.
   *
   * <p>Can be used for usage help and controlling whether the "no" prefix is allowed.
   */
  public boolean usesBooleanValueSyntax() {
    return getType().equals(boolean.class)
        || getType().equals(TriState.class)
        || getConverter() instanceof BoolOrEnumConverter;
  }

  /** Returns the evaluated default value for this option & memoizes the result. */
  public Object getDefaultValue() {
    if (defaultValue != null) {
      return defaultValue;
    }

    if (isSpecialNullDefault()) {
      return allowsMultiple() ? ImmutableList.of() : null;
    }

    Converter<?> converter = getConverter();
    String defaultValueAsString = getUnparsedDefaultValue();
    try {
      Object convertedDefaultValue = converter.convert(defaultValueAsString);
      defaultValue =
          allowsMultiple()
              ? maybeWrapMultipleDefaultValue(convertedDefaultValue)
              : convertedDefaultValue;
    } catch (OptionsParsingException e) {
      throw new ConstructionException(
          String.format(
              "OptionsParsingException while retrieving the default value for %s: %s",
              getField().getName(), e.getMessage()),
          e);
    }

    return defaultValue;
  }

  /**
   * Wraps a converted default value into a {@link List} if the converter doesn't do it on its own.
   *
   * <p>This is to make sure multiple ({@link Option#allowMultiple()}) options' default values are
   * always converted to a list representation.
   *
   * <p>In general it mimics the {@link RepeatableOptionValueDescription# addOptionInstance}
   * behavior: multiple option default value is treated as if it appeared on the command line only
   * once with the specified value.
   *
   * <p>Note that on a command line multiple options can appear multiple times while each can
   * support multiple values (e.g. comma-separated - depending on a converter). Thus default value
   * for multiple option is (depending on the converter) a strict subset of the set of potential
   * values for the option.
   */
  @SuppressWarnings("unchecked") // Not an unchecked cast - there's an explicit type check before it
  private static List<Object> maybeWrapMultipleDefaultValue(Object convertedDefaultValue) {
    if (convertedDefaultValue instanceof List) {
      return (List<Object>) convertedDefaultValue;
    } else {
      return Arrays.asList(convertedDefaultValue);
    }
  }

  /**
   * {@link OptionDefinition} is really a wrapper around a {@link Field} that caches information
   * obtained through reflection. Checking that the fields they represent are equal is sufficient to
   * check that two {@link OptionDefinition} objects are equal.
   */
  @Override
  public boolean equals(Object object) {
    if (!(object instanceof OptionDefinition)) {
      return false;
    }
    OptionDefinition otherOption = (OptionDefinition) object;
    return field.equals(otherOption.field);
  }

  @Override
  public int hashCode() {
    return field.hashCode();
  }

  @Override
  public int compareTo(OptionDefinition o) {
    return getOptionName().compareTo(o.getOptionName());
  }

  @Override
  public String toString() {
    return String.format("option '--%s'", getOptionName());
  }

  static final Comparator<OptionDefinition> BY_OPTION_NAME =
      Comparator.comparing(OptionDefinition::getOptionName);

  /**
   * An ordering relation for option-field fields that first groups together options of the same
   * category, then sorts by name within the category.
   */
  static final Comparator<OptionDefinition> BY_CATEGORY =
      comparing(OptionDefinition::getOptionCategory).thenComparing(BY_OPTION_NAME);
}
