// 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 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.Collections;
import java.util.Comparator;

/**
 * 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> {

  // 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#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#expansionFunction()} ()} */
  Class<? extends ExpansionFunction> getExpansionFunction() {
    return optionAnnotation.expansionFunction();
  }

  /** {@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 getUnparsedDefaultValue().equals("null") && !getType().isPrimitive();
  }

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

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

  /**
   * Returns whether the arg is an expansion option defined by an expansion function (and not a
   * constant expansion value).
   */
  public boolean usesExpansionFunction() {
    return getExpansionFunction() != ExpansionFunction.class;
  }

  /**
   * 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 || isSpecialNullDefault()) {
      return defaultValue;
    }
    Converter<?> converter = getConverter();
    String defaultValueAsString = getUnparsedDefaultValue();
    boolean allowsMultiple = allowsMultiple();
    // If the option allows multiple values then we intentionally return the empty list as
    // the default value of this option since it is not always the case that an option
    // that allows multiple values will have a converter that returns a list value.
    if (allowsMultiple) {
      defaultValue = Collections.emptyList();
    } else {
      // Otherwise try to convert the default value using the converter
      try {
        defaultValue = converter.convert(defaultValueAsString);
      } catch (OptionsParsingException e) {
        throw new ConstructionException(
            String.format(
                "OptionsParsingException while retrieving the default value for %s: %s",
                getField().getName(), e.getMessage()),
            e);
      }
    }
    return defaultValue;
  }

  /**
   * {@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 =
      (left, right) -> {
        int r = left.getOptionCategory().compareTo(right.getOptionCategory());
        return r == 0 ? BY_OPTION_NAME.compare(left, right) : r;
      };
}
