// 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.devtools.common.options.OptionDefinition.NotAnOptionException;
import com.google.devtools.common.options.OptionsParser.ConstructionException;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
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 {

  /**
   * Cache for the options in an OptionsBase.
   *
   * <p>Mapping from options class to a list of all {@code OptionFields} in that class. The map
   * entries are unordered, but the fields in the lists are ordered alphabetically. This caches the
   * work of reflection done for the same {@code optionsBase} across multiple {@link OptionsData}
   * instances, and must be used through the thread safe {@link
   * #getAllOptionDefinitionsForClass(Class)}
   */
  private static final Map<Class<? extends OptionsBase>, ImmutableList<OptionDefinition>>
      allOptionsFields = new HashMap<>();

  /** Returns all {@code optionDefinitions}, ordered by their option name (not their field name). */
  public static synchronized ImmutableList<OptionDefinition> getAllOptionDefinitionsForClass(
      Class<? extends OptionsBase> optionsClass) {
    return allOptionsFields.computeIfAbsent(
        optionsClass,
        optionsBaseClass ->
            Arrays.stream(optionsBaseClass.getFields())
                .map(
                    field -> {
                      try {
                        return OptionDefinition.extractOptionDefinition(field);
                      } catch (NotAnOptionException e) {
                        // Ignore non-@Option annotated fields. Requiring all fields in the
                        // OptionsBase to be @Option-annotated requires a depot cleanup.
                        return null;
                      }
                    })
                .filter(Objects::nonNull)
                .sorted(OptionDefinition.BY_OPTION_NAME)
                .collect(ImmutableList.toImmutableList()));
  }

  /**
   * 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 OptionDefinition}. 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, OptionDefinition> nameToField;

  /**
   * For options that have an "OldName", this is a mapping from old name to its corresponding {@code
   * OptionDefinition}. 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, OptionDefinition> oldNameToField;

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


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

  private IsolatedOptionsData(
      Map<Class<? extends OptionsBase>, Constructor<?>> optionsClasses,
      Map<String, OptionDefinition> nameToField,
      Map<String, OptionDefinition> oldNameToField,
      Map<Character, OptionDefinition> abbrevToField,
      Map<Class<? extends OptionsBase>, Boolean> usesOnlyCoreTypes) {
    this.optionsClasses = ImmutableMap.copyOf(optionsClasses);
    this.nameToField = ImmutableMap.copyOf(nameToField);
    this.oldNameToField = ImmutableMap.copyOf(oldNameToField);
    this.abbrevToField = ImmutableMap.copyOf(abbrevToField);
    this.usesOnlyCoreTypes = ImmutableMap.copyOf(usesOnlyCoreTypes);
  }

  protected IsolatedOptionsData(IsolatedOptionsData other) {
    this(
        other.optionsClasses,
        other.nameToField,
        other.oldNameToField,
        other.abbrevToField,
        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);
  }

  /**
   * Returns the option in this parser by the provided name, or {@code null} if none is found. This
   * will match both the canonical name of an option, and any old name listed that we still accept.
   */
  public OptionDefinition getOptionDefinitionFromName(String name) {
    return nameToField.getOrDefault(name, oldNameToField.get(name));
  }

  /**
   * Returns all {@link OptionDefinition} objects loaded, mapped by their canonical names. 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, OptionDefinition>> getAllOptionDefinitions() {
    return nameToField.entrySet();
  }

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

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

  /**
   * Generic method to check for collisions between the names we give options. Useful for checking
   * both single-character abbreviations and full names.
   */
  private static <A> void checkForCollisions(
      Map<A, OptionDefinition> aFieldMap, A optionName, String description)
      throws DuplicateOptionDeclarationException {
    if (aFieldMap.containsKey(optionName)) {
      throw new DuplicateOptionDeclarationException(
          "Duplicate option name, due to " + description + ": --" + optionName);
    }
  }

  /**
   * All options, even non-boolean ones, should check that they do not conflict with previously
   * loaded boolean options.
   */
  private static void checkForBooleanAliasCollisions(
      Map<String, String> booleanAliasMap, String optionName, String description)
      throws DuplicateOptionDeclarationException {
    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));
    }
  }

  /**
   * For an {@code option} of boolean type, this checks that the boolean alias does not conflict
   * with other names, and adds the boolean alias to a list so that future flags can find if they
   * conflict with a boolean alias..
   */
  private static void checkAndUpdateBooleanAliases(
      Map<String, OptionDefinition> nameToFieldMap,
      Map<String, OptionDefinition> oldNameToFieldMap,
      Map<String, String> booleanAliasMap,
      String optionName)
      throws DuplicateOptionDeclarationException {
    // Check that the negating alias does not conflict with existing flags.
    checkForCollisions(nameToFieldMap, "no" + optionName, "boolean option alias");
    checkForCollisions(oldNameToFieldMap, "no" + optionName, "boolean option alias");

    // Record that the boolean option takes up additional namespace for its negating alias.
    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<String, OptionDefinition> nameToFieldBuilder = new LinkedHashMap<>();
    Map<String, OptionDefinition> oldNameToFieldBuilder = new LinkedHashMap<>();
    Map<Character, OptionDefinition> abbrevToFieldBuilder = 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<>();

    // Combine the option definitions for these options classes, and check that they do not
    // conflict. The options are individually checked for correctness at compile time in the
    // OptionProcessor.
    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<OptionDefinition> optionDefinitions =
          getAllOptionDefinitionsForClass(parsedOptionsClass);

      for (OptionDefinition optionDefinition : optionDefinitions) {
        try {
          String optionName = optionDefinition.getOptionName();
          checkForCollisions(nameToFieldBuilder, optionName, "option name collision");
          checkForCollisions(
              oldNameToFieldBuilder,
              optionName,
              "option name collision with another option's old name");
          checkForBooleanAliasCollisions(booleanAliasMap, optionName, "option");
          if (optionDefinition.usesBooleanValueSyntax()) {
            checkAndUpdateBooleanAliases(
                nameToFieldBuilder, oldNameToFieldBuilder, booleanAliasMap, optionName);
          }
          nameToFieldBuilder.put(optionName, optionDefinition);

          if (!optionDefinition.getOldOptionName().isEmpty()) {
            String oldName = optionDefinition.getOldOptionName();
            checkForCollisions(
                nameToFieldBuilder,
                oldName,
                "old option name collision with another option's canonical name");
            checkForCollisions(
                oldNameToFieldBuilder,
                oldName,
                "old option name collision with another old option name");
            checkForBooleanAliasCollisions(booleanAliasMap, oldName, "old option name");
            // If boolean, repeat the alias dance for the old name.
            if (optionDefinition.usesBooleanValueSyntax()) {
              checkAndUpdateBooleanAliases(
                  nameToFieldBuilder, oldNameToFieldBuilder, booleanAliasMap, oldName);
            }
            // Now that we've checked for conflicts, confidently store the old name.
            oldNameToFieldBuilder.put(oldName, optionDefinition);
          }
          if (optionDefinition.getAbbreviation() != '\0') {
            checkForCollisions(
                abbrevToFieldBuilder, optionDefinition.getAbbreviation(), "option abbreviation");
            abbrevToFieldBuilder.put(optionDefinition.getAbbreviation(), optionDefinition);
          }
        } catch (DuplicateOptionDeclarationException e) {
          throw new ConstructionException(e);
        }
      }

      boolean usesOnlyCoreTypes = parsedOptionsClass.isAnnotationPresent(UsesOnlyCoreTypes.class);
      if (usesOnlyCoreTypes) {
        // Validate that @UsesOnlyCoreTypes was used correctly.
        for (OptionDefinition optionDefinition : optionDefinitions) {
          // 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(optionDefinition.getType())) {
            throw new ConstructionException(
                "Options class '"
                    + parsedOptionsClass.getName()
                    + "' is marked as "
                    + "@UsesOnlyCoreTypes, but field '"
                    + optionDefinition.getField().getName()
                    + "' has type '"
                    + optionDefinition.getType().getName()
                    + "'");
          }
        }
      }
      usesOnlyCoreTypesBuilder.put(parsedOptionsClass, usesOnlyCoreTypes);
    }

    return new IsolatedOptionsData(
        constructorBuilder,
        nameToFieldBuilder,
        oldNameToFieldBuilder,
        abbrevToFieldBuilder,
        usesOnlyCoreTypesBuilder);
  }

}
