// 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.Lists;
import com.google.common.collect.Maps;
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.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.concurrent.Immutable;

/**
 * An immutable selection of options data corresponding to a set of 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.
 */
// TODO(brandjon): This class is technically not necessarily immutable due to optionsDefault
// accepting Object values, and the List in allOptionsField should be ImmutableList. Either fix
// this or remove @Immutable.
@Immutable
class IsolatedOptionsData extends OpaqueOptionsData {

  /**
   * These are the options-declaring classes which are annotated with {@link Option} annotations.
   */
  private final ImmutableMap<Class<? extends OptionsBase>, Constructor<?>> optionsClasses;

  /** Maps option name to Option-annotated Field. */
  private final ImmutableMap<String, Field> nameToField;

  /** Maps option abbreviation to Option-annotated Field. */
  private final ImmutableMap<Character, Field> abbrevToField;

  /** For each options class, contains a list of all Option-annotated fields in that class. */
  private final ImmutableMap<Class<? extends OptionsBase>, List<Field>> allOptionsFields;

  /** Mapping from each Option-annotated field to the default value for that field. */
  // Immutable like the others, but uses Collections.unmodifiableMap because of null values.
  private final Map<Field, Object> optionDefaults;

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

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

  private IsolatedOptionsData(
      Map<Class<? extends OptionsBase>, Constructor<?>> optionsClasses,
      Map<String, Field> nameToField,
      Map<Character, Field> abbrevToField,
      Map<Class<? extends OptionsBase>, List<Field>> allOptionsFields,
      Map<Field, Object> optionDefaults,
      Map<Field, Converter<?>> converters,
      Map<Field, Boolean> allowMultiple) {
    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);
  }

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

  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);
  }

  public Iterable<Map.Entry<String, Field>> getAllNamedFields() {
    return nameToField.entrySet();
  }

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

  public List<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);
  }

  /**
   * 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 AssertionError("Type of multiple occurrence option must be a List<...>");
      }
      ParameterizedType pfieldType = (ParameterizedType) fieldType;
      if (pfieldType.getRawType() != List.class) {
        throw new AssertionError("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 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 AssertionError(
            "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 AssertionError(e);
    }
  }

  private static List<Field> getAllAnnotatedFields(Class<? extends OptionsBase> optionsClass) {
    List<Field> allFields = Lists.newArrayList();
    for (Field field : optionsClass.getFields()) {
      if (field.isAnnotationPresent(Option.class)) {
        allFields.add(field);
      }
    }
    if (allFields.isEmpty()) {
      throw new IllegalStateException(optionsClass + " has no public @Option-annotated fields");
    }
    return ImmutableList.copyOf(allFields);
  }

  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;
  }

  /**
   * 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) {
    Map<Class<? extends OptionsBase>, Constructor<?>> constructorBuilder = Maps.newHashMap();
    Map<Class<? extends OptionsBase>, List<Field>> allOptionsFieldsBuilder = Maps.newHashMap();
    Map<String, Field> nameToFieldBuilder = Maps.newHashMap();
    Map<Character, Field> abbrevToFieldBuilder = Maps.newHashMap();
    Map<Field, Object> optionDefaultsBuilder = Maps.newHashMap();
    Map<Field, Converter<?>> convertersBuilder = Maps.newHashMap();
    Map<Field, Boolean> allowMultipleBuilder = Maps.newHashMap();

    // 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");
      }
      List<Field> fields = getAllAnnotatedFields(parsedOptionsClass);
      allOptionsFieldsBuilder.put(parsedOptionsClass, fields);

      for (Field field : fields) {
        Option annotation = field.getAnnotation(Option.class);

        if (annotation.name() == null) {
          throw new AssertionError("Option cannot have a null name");
        }

        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 AssertionError("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 AssertionError("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 AssertionError("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 AssertionError("If the converter return type of a multiple occurance " +
                  "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 AssertionError("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 AssertionError("Type of field (" + fieldType +
                ") must be assignable from the converter " +
                "return type (" + converterResultType + ")");
          }
        }

        if (nameToFieldBuilder.put(annotation.name(), field) != null) {
          throw new DuplicateOptionDeclarationException(
              "Duplicate option name: --" + annotation.name());
        }
        if (!annotation.oldName().isEmpty()) {
          if (nameToFieldBuilder.put(annotation.oldName(), field) != null) {
            throw new DuplicateOptionDeclarationException(
                "Old option name duplicates option name: --" + annotation.oldName());
          }
        }
        if (annotation.abbrev() != '\0') {
          if (abbrevToFieldBuilder.put(annotation.abbrev(), field) != null) {
            throw new DuplicateOptionDeclarationException(
                  "Duplicate option abbrev: -" + annotation.abbrev());
          }
        }

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

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

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

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