// 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 java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
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 ConcurrentMap<Class<? extends OptionsBase>, ImmutableList<OptionDefinition>>
      allOptionsFields = new ConcurrentHashMap<>();

  /** Returns all {@code optionDefinitions}, ordered by their option name (not their field name). */
  public static 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);
  }

}
