// Copyright 2014 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.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Ordering;
import com.google.devtools.common.options.OptionsParser.ConstructionException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.concurrent.Immutable;

/**
 * A selection of options data corresponding to a set of {@link OptionsBase} subclasses (options
 * classes). The data is collected using reflection, which can be expensive. Therefore this class
 * can be used internally to cache the results.
 *
 * <p>The data is isolated in the sense that it has not yet been processed to add
 * inter-option-dependent information -- namely, the results of evaluating expansion functions. The
 * {@link OptionsData} subclass stores this added information. The reason for the split is so that
 * we can avoid exposing to expansion functions the effects of evaluating other expansion functions,
 * to ensure that the order in which they run is not significant.
 *
 * <p>This class is immutable so long as the converters and default values associated with the
 * options are immutable.
 */
@Immutable
public class IsolatedOptionsData extends OpaqueOptionsData {

  /**
   * Mapping from each options class to its no-arg constructor. Entries appear in the same order
   * that they were passed to {@link #from(Collection)}.
   */
  private final ImmutableMap<Class<? extends OptionsBase>, Constructor<?>> optionsClasses;

  /**
   * Mapping from option name to {@code @Option}-annotated field. Entries appear ordered first by
   * their options class (the order in which they were passed to {@link #from(Collection)}, and then
   * in alphabetic order within each options class.
   */
  private final ImmutableMap<String, Field> nameToField;

  /** Mapping from option abbreviation to {@code Option}-annotated field (unordered). */
  private final ImmutableMap<Character, Field> abbrevToField;

  /**
   * Mapping from options class to a list of all {@code Option}-annotated fields in that class. The
   * map entries are unordered, but the fields in the lists are ordered alphabetically.
   */
  private final ImmutableMap<Class<? extends OptionsBase>, ImmutableList<Field>> allOptionsFields;

  /**
   * Mapping from each {@code Option}-annotated field to the default value for that field
   * (unordered).
   *
   * <p>(This is immutable like the others, but uses {@code Collections.unmodifiableMap} to support
   * null values.)
   */
  private final Map<Field, Object> optionDefaults;

  /**
   * Mapping from each {@code Option}-annotated field to the proper converter (unordered).
   *
   * @see #findConverter
   */
  private final ImmutableMap<Field, Converter<?>> converters;

  /**
   * Mapping from each {@code Option}-annotated field to a boolean for whether that field allows
   * multiple values (unordered).
   */
  private final ImmutableMap<Field, Boolean> allowMultiple;

  /**
   * Mapping from each options class to whether or not it has the {@link UsesOnlyCoreTypes}
   * annotation (unordered).
   */
  private final ImmutableMap<Class<? extends OptionsBase>, Boolean> usesOnlyCoreTypes;

  /** These categories used to indicate OptionUsageRestrictions, but no longer. */
  private static final ImmutableList<String> DEPRECATED_CATEGORIES = ImmutableList.of(
      "undocumented", "hidden", "internal");

  private IsolatedOptionsData(
      Map<Class<? extends OptionsBase>,
      Constructor<?>> optionsClasses,
      Map<String, Field> nameToField,
      Map<Character, Field> abbrevToField,
      Map<Class<? extends OptionsBase>, ImmutableList<Field>> allOptionsFields,
      Map<Field, Object> optionDefaults,
      Map<Field, Converter<?>> converters,
      Map<Field, Boolean> allowMultiple,
      Map<Class<? extends OptionsBase>, Boolean> usesOnlyCoreTypes) {
    this.optionsClasses = ImmutableMap.copyOf(optionsClasses);
    this.nameToField = ImmutableMap.copyOf(nameToField);
    this.abbrevToField = ImmutableMap.copyOf(abbrevToField);
    this.allOptionsFields = ImmutableMap.copyOf(allOptionsFields);
    // Can't use an ImmutableMap here because of null values.
    this.optionDefaults = Collections.unmodifiableMap(optionDefaults);
    this.converters = ImmutableMap.copyOf(converters);
    this.allowMultiple = ImmutableMap.copyOf(allowMultiple);
    this.usesOnlyCoreTypes = ImmutableMap.copyOf(usesOnlyCoreTypes);
  }

  protected IsolatedOptionsData(IsolatedOptionsData other) {
    this(
        other.optionsClasses,
        other.nameToField,
        other.abbrevToField,
        other.allOptionsFields,
        other.optionDefaults,
        other.converters,
        other.allowMultiple,
        other.usesOnlyCoreTypes);
  }

  /**
   * Returns all options classes indexed by this options data object, in the order they were passed
   * to {@link #from(Collection)}.
   */
  public Collection<Class<? extends OptionsBase>> getOptionsClasses() {
    return optionsClasses.keySet();
  }

  @SuppressWarnings("unchecked") // The construction ensures that the case is always valid.
  public <T extends OptionsBase> Constructor<T> getConstructor(Class<T> clazz) {
    return (Constructor<T>) optionsClasses.get(clazz);
  }

  public Field getFieldFromName(String name) {
    return nameToField.get(name);
  }

  /**
   * Returns all pairs of option names (not field names) and their corresponding {@link Field}
   * objects. Entries appear ordered first by their options class (the order in which they were
   * passed to {@link #from(Collection)}, and then in alphabetic order within each options class.
   */
  public Iterable<Map.Entry<String, Field>> getAllNamedFields() {
    return nameToField.entrySet();
  }

  public Field getFieldForAbbrev(char abbrev) {
    return abbrevToField.get(abbrev);
  }

  /**
   * Returns a list of all {@link Field} objects for options in the given options class, ordered
   * alphabetically by option name.
   */
  public ImmutableList<Field> getFieldsForClass(Class<? extends OptionsBase> optionsClass) {
    return allOptionsFields.get(optionsClass);
  }

  public Object getDefaultValue(Field field) {
    return optionDefaults.get(field);
  }

  public Converter<?> getConverter(Field field) {
    return converters.get(field);
  }

  public boolean getAllowMultiple(Field field) {
    return allowMultiple.get(field);
  }

  public boolean getUsesOnlyCoreTypes(Class<? extends OptionsBase> optionsClass) {
    return usesOnlyCoreTypes.get(optionsClass);
  }

  /**
   * 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}.
   */
  private static Type getFieldSingularType(Field field, Option annotation) {
    Type fieldType = field.getGenericType();
    if (annotation.allowMultiple()) {
      // If the type isn't a List<T>, this is an error in the option's declaration.
      if (!(fieldType instanceof ParameterizedType)) {
        throw new ConstructionException("Type of multiple occurrence option must be a List<...>");
      }
      ParameterizedType pfieldType = (ParameterizedType) fieldType;
      if (pfieldType.getRawType() != List.class) {
        throw new ConstructionException("Type of multiple occurrence option must be a List<...>");
      }
      fieldType = pfieldType.getActualTypeArguments()[0];
    }
    return fieldType;
  }

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

  /** Returns whether a field has Void type. */
  static boolean isVoidField(Field field) {
    return field.getType().equals(Void.class);
  }

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

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

  /**
   * Given an {@code @Option}-annotated field, retrieves the {@link Converter} that will be used,
   * taking into account the default converters if an explicit one is not specified.
   */
  static Converter<?> findConverter(Field optionField) {
    Option annotation = optionField.getAnnotation(Option.class);
    if (annotation.converter() == Converter.class) {
      // No converter provided, use the default one.
      Type type = getFieldSingularType(optionField, annotation);
      Converter<?> converter = Converters.DEFAULT_CONVERTERS.get(type);
      if (converter == null) {
        throw new ConstructionException(
            "No converter found for "
                + type
                + "; possible fix: add "
                + "converter=... to @Option annotation for "
                + optionField.getName());
      }
      return converter;
    }
    try {
      // Instantiate the given Converter class.
      Class<?> converter = annotation.converter();
      Constructor<?> constructor = converter.getConstructor();
      return (Converter<?>) constructor.newInstance();
    } catch (Exception e) {
      // This indicates an error in the Converter, and should be discovered the first time it is
      // used.
      throw new ConstructionException(e);
    }
  }

  private static final Ordering<Field> fieldOrdering =
      new Ordering<Field>() {
    @Override
    public int compare(Field f1, Field f2) {
      String n1 = f1.getAnnotation(Option.class).name();
      String n2 = f2.getAnnotation(Option.class).name();
      return n1.compareTo(n2);
    }
  };

  /**
   * Return all {@code @Option}-annotated fields, alphabetically ordered by their option name (not
   * their field name).
   */
  private static ImmutableList<Field> getAllAnnotatedFieldsSorted(
      Class<? extends OptionsBase> optionsClass) {
    List<Field> unsortedFields = new ArrayList<>();
    for (Field field : optionsClass.getFields()) {
      if (field.isAnnotationPresent(Option.class)) {
        unsortedFields.add(field);
      }
    }
    return fieldOrdering.immutableSortedCopy(unsortedFields);
  }

  private static Object retrieveDefaultFromAnnotation(Field optionField) {
    Converter<?> converter = findConverter(optionField);
    String defaultValueAsString = OptionsParserImpl.getDefaultOptionString(optionField);
    // Special case for "null"
    if (OptionsParserImpl.isSpecialNullDefault(defaultValueAsString, optionField)) {
      return null;
    }
    boolean allowsMultiple = optionField.getAnnotation(Option.class).allowMultiple();
    // 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) {
      return Collections.emptyList();
    }
    // Otherwise try to convert the default value using the converter
    Object convertedValue;
    try {
      convertedValue = converter.convert(defaultValueAsString);
    } catch (OptionsParsingException e) {
      throw new IllegalStateException("OptionsParsingException while "
          + "retrieving default for " + optionField.getName() + ": "
          + e.getMessage());
    }
    return convertedValue;
  }

  private static <A> void checkForCollisions(
      Map<A, Field> aFieldMap,
      A optionName,
      String description) {
    if (aFieldMap.containsKey(optionName)) {
      throw new DuplicateOptionDeclarationException(
          "Duplicate option name, due to " + description + ": --" + optionName);
    }
  }

  private static void checkForBooleanAliasCollisions(
      Map<String, String> booleanAliasMap,
      String optionName,
      String description) {
    if (booleanAliasMap.containsKey(optionName)) {
      throw new DuplicateOptionDeclarationException(
          "Duplicate option name, due to "
              + description
              + " --"
              + optionName
              + ", it conflicts with a negating alias for boolean flag --"
              + booleanAliasMap.get(optionName));
    }
  }

  private static void checkAndUpdateBooleanAliases(
      Map<String, Field> nameToFieldMap,
      Map<String, String> booleanAliasMap,
      String optionName) {
    // Check that the negating alias does not conflict with existing flags.
    checkForCollisions(nameToFieldMap, "no_" + optionName, "boolean option alias");
    checkForCollisions(nameToFieldMap, "no" + optionName, "boolean option alias");

    // Record that the boolean option takes up additional namespace for its negating alias.
    booleanAliasMap.put("no_" + optionName, optionName);
    booleanAliasMap.put("no" + optionName, optionName);
  }

  /**
   * Constructs an {@link IsolatedOptionsData} object for a parser that knows about the given
   * {@link OptionsBase} classes. No inter-option analysis is done. Performs basic sanity checking
   * on each option in isolation.
   */
  static IsolatedOptionsData from(Collection<Class<? extends OptionsBase>> classes) {
    // Mind which fields have to preserve order.
    Map<Class<? extends OptionsBase>, Constructor<?>> constructorBuilder = new LinkedHashMap<>();
    Map<Class<? extends OptionsBase>, ImmutableList<Field>> allOptionsFieldsBuilder =
        new HashMap<>();
    Map<String, Field> nameToFieldBuilder = new LinkedHashMap<>();
    Map<Character, Field> abbrevToFieldBuilder = new HashMap<>();
    Map<Field, Object> optionDefaultsBuilder = new HashMap<>();
    Map<Field, Converter<?>> convertersBuilder = new HashMap<>();
    Map<Field, Boolean> allowMultipleBuilder = new HashMap<>();

    // Maps the negated boolean flag aliases to the original option name.
    Map<String, String> booleanAliasMap = new HashMap<>();

    Map<Class<? extends OptionsBase>, Boolean> usesOnlyCoreTypesBuilder = new HashMap<>();

    // Read all Option annotations:
    for (Class<? extends OptionsBase> parsedOptionsClass : classes) {
      try {
        Constructor<? extends OptionsBase> constructor =
            parsedOptionsClass.getConstructor();
        constructorBuilder.put(parsedOptionsClass, constructor);
      } catch (NoSuchMethodException e) {
        throw new IllegalArgumentException(parsedOptionsClass
            + " lacks an accessible default constructor");
      }
      ImmutableList<Field> fields = getAllAnnotatedFieldsSorted(parsedOptionsClass);
      allOptionsFieldsBuilder.put(parsedOptionsClass, fields);

      for (Field field : fields) {
        Option annotation = field.getAnnotation(Option.class);
        String optionName = annotation.name();
        if (optionName == null) {
          throw new ConstructionException("Option cannot have a null name");
        }

        if (DEPRECATED_CATEGORIES.contains(annotation.category())) {
          throw new ConstructionException(
              "Documentation level is no longer read from the option category. Category \""
                  + annotation.category() + "\" in option \"" + optionName + "\" is disallowed.");
        }

        Type fieldType = getFieldSingularType(field, annotation);

        // Get the converter return type.
        @SuppressWarnings("rawtypes")
        Class<? extends Converter> converter = annotation.converter();
        if (converter == Converter.class) {
          Converter<?> actualConverter = Converters.DEFAULT_CONVERTERS.get(fieldType);
          if (actualConverter == null) {
            throw new ConstructionException("Cannot find converter for field of type "
                + field.getType() + " named " + field.getName()
                + " in class " + field.getDeclaringClass().getName());
          }
          converter = actualConverter.getClass();
        }
        if (Modifier.isAbstract(converter.getModifiers())) {
          throw new ConstructionException("The converter type " + converter
              + " must be a concrete type");
        }
        Type converterResultType;
        try {
          Method convertMethod = converter.getMethod("convert", String.class);
          converterResultType = GenericTypeHelper.getActualReturnType(converter, convertMethod);
        } catch (NoSuchMethodException e) {
          throw new ConstructionException(
              "A known converter object doesn't implement the convert method");
        }

        if (annotation.allowMultiple()) {
          if (GenericTypeHelper.getRawType(converterResultType) == List.class) {
            Type elementType =
                ((ParameterizedType) converterResultType).getActualTypeArguments()[0];
            if (!GenericTypeHelper.isAssignableFrom(fieldType, elementType)) {
              throw new ConstructionException(
                  "If the converter return type of a multiple occurrence option is a list, then "
                      + "the type of list elements ("
                      + fieldType
                      + ") must be assignable from the converter list element type ("
                      + elementType
                      + ")");
            }
          } else {
            if (!GenericTypeHelper.isAssignableFrom(fieldType, converterResultType)) {
              throw new ConstructionException(
                  "Type of list elements ("
                      + fieldType
                      + ") for multiple occurrence option must be assignable from the converter "
                      + "return type ("
                      + converterResultType
                      + ")");
            }
          }
        } else {
          if (!GenericTypeHelper.isAssignableFrom(fieldType, converterResultType)) {
            throw new ConstructionException(
                "Type of field ("
                    + fieldType
                    + ") must be assignable from the converter return type ("
                    + converterResultType
                    + ")");
          }
        }

        if (isBooleanField(field)) {
          checkAndUpdateBooleanAliases(nameToFieldBuilder, booleanAliasMap, optionName);
        }

        checkForCollisions(nameToFieldBuilder, optionName, "option");
        checkForBooleanAliasCollisions(booleanAliasMap, optionName, "option");
        nameToFieldBuilder.put(optionName, field);

        if (!annotation.oldName().isEmpty()) {
          String oldName = annotation.oldName();
          checkForCollisions(nameToFieldBuilder, oldName, "old option name");
          checkForBooleanAliasCollisions(booleanAliasMap, oldName, "old option name");
          nameToFieldBuilder.put(annotation.oldName(), field);

          // If boolean, repeat the alias dance for the old name.
          if (isBooleanField(field)) {
            checkAndUpdateBooleanAliases(nameToFieldBuilder, booleanAliasMap, oldName);
          }
        }
        if (annotation.abbrev() != '\0') {
          checkForCollisions(abbrevToFieldBuilder, annotation.abbrev(), "option abbreviation");
          abbrevToFieldBuilder.put(annotation.abbrev(), field);
        }

        optionDefaultsBuilder.put(field, retrieveDefaultFromAnnotation(field));

        convertersBuilder.put(field, findConverter(field));

        allowMultipleBuilder.put(field, annotation.allowMultiple());

        }

      boolean usesOnlyCoreTypes = parsedOptionsClass.isAnnotationPresent(UsesOnlyCoreTypes.class);
      if (usesOnlyCoreTypes) {
        // Validate that @UsesOnlyCoreTypes was used correctly.
        for (Field field : fields) {
          // The classes in coreTypes are all final. But even if they weren't, we only want to check
          // for exact matches; subclasses would not be considered core types.
          if (!UsesOnlyCoreTypes.CORE_TYPES.contains(field.getType())) {
            throw new ConstructionException(
                "Options class '" + parsedOptionsClass.getName() + "' is marked as "
                + "@UsesOnlyCoreTypes, but field '" + field.getName()
                + "' has type '" + field.getType().getName() + "'");
          }
        }
      }
      usesOnlyCoreTypesBuilder.put(parsedOptionsClass, usesOnlyCoreTypes);
    }

    return new IsolatedOptionsData(
        constructorBuilder,
        nameToFieldBuilder,
        abbrevToFieldBuilder,
        allOptionsFieldsBuilder,
        optionDefaultsBuilder,
        convertersBuilder,
        allowMultipleBuilder,
        usesOnlyCoreTypesBuilder);
  }

}
