// 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.build.lib.analysis.skylark;

import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.skylark.annotations.SkylarkConfigurationField;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute.AbstractLabelLateBoundDefault;
import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skylarkbuildapi.LateBoundDefaultApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkInterfaceUtils;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.syntax.Printer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.annotation.concurrent.Immutable;

/**
 * An implementation of {@link LateBoundDefault} which obtains a late-bound attribute value (of type
 * 'label') specifically by skylark configuration fragment name and field name, as registered by
 * {@link SkylarkConfigurationField}.
 *
 * <p>For example, a SkylarkLateBoundDefault on "java" and "toolchain" would require a valid
 * configuration fragment named "java" with a method annotated with {@link
 * SkylarkConfigurationField} of name "toolchain". This {@link LateBoundDefault} would provide a
 * late-bound dependency (defined by the label returned by that configuration field) in the current
 * target configuration.
 */
@Immutable
@AutoCodec
public class SkylarkLateBoundDefault<FragmentT> extends AbstractLabelLateBoundDefault<FragmentT>
    implements LateBoundDefaultApi {

  private final Method method;
  private final String fragmentName;
  private final String fragmentFieldName;

  @Override
  public Label resolve(Rule rule, AttributeMap attributes, FragmentT config) {
    try {
      Object result = method.invoke(config);
      return (Label) result;
    } catch (IllegalAccessException | InvocationTargetException e) {
      // Configuration field methods should not throw either of these exceptions.
      throw new AssertionError("Method invocation failed: " + e);
    }
  }

  /**
   * Returns the {@link SkylarkConfigurationField} annotation corresponding to this method.
   */
  private static Label getDefaultLabel(
      SkylarkConfigurationField annotation, String toolsRepository) {
    if (annotation.defaultLabel().isEmpty()) {
      return null;
    }
    Label defaultLabel = annotation.defaultInToolRepository()
        ? Label.parseAbsoluteUnchecked(toolsRepository + annotation.defaultLabel())
        : Label.parseAbsoluteUnchecked(annotation.defaultLabel());
    return defaultLabel;
  }

  private SkylarkLateBoundDefault(SkylarkConfigurationField annotation,
      Class<FragmentT> fragmentClass, String fragmentName, Method method, String toolsRepository) {
    this(
        getDefaultLabel(annotation, toolsRepository),
        fragmentClass,
        method,
        fragmentName,
        annotation.name());
  }

  @AutoCodec.VisibleForSerialization
  @AutoCodec.Instantiator
  SkylarkLateBoundDefault(
      Label defaultVal,
      Class<FragmentT> fragmentClass,
      Method method,
      String fragmentName,
      String fragmentFieldName) {
    super(/*useHostConfiguration=*/ false, fragmentClass, defaultVal);
    this.method = method;
    this.fragmentName = fragmentName;
    this.fragmentFieldName = fragmentFieldName;
  }

  /**
   * Returns the skylark name of the configuration fragment that this late bound default requires.
   */
  public String getFragmentName() {
    return fragmentName;
  }

  /**
   * Returns the skylark name of the configuration field name, as registered by
   * {@link SkylarkConfigurationField} annotation on the configuration fragment.
   */
  public String getFragmentFieldName() {
    return fragmentFieldName;
  }

  @Override
  public void repr(Printer printer) {
    printer.format("<late-bound default>");
  }

  /** For use by @AutoCodec since the {@link #defaultValue} field is hard for it to process. */
  @AutoCodec.VisibleForSerialization
  Label getDefaultVal() {
    return getDefault();
  }

  /**
   * An exception thrown if a user specifies an invalid configuration field identifier.
   *
   * @see SkylarkConfigurationField
   **/
  public static class InvalidConfigurationFieldException extends Exception {
    public InvalidConfigurationFieldException(String message) {
      super(message);
    }
  }


  private static class CacheKey {
    private final Class<?> fragmentClass;
    private final String toolsRepository;

    private CacheKey(Class<?> fragmentClass,
        String toolsRepository) {
      this.fragmentClass = fragmentClass;
      this.toolsRepository = toolsRepository;
    }

    @Override
    public boolean equals(Object object) {
      if (object == this) {
        return true;
      } else if (!(object instanceof CacheKey)) {
        return false;
      } else {
        CacheKey cacheKey = (CacheKey) object;
        return fragmentClass.equals(cacheKey.fragmentClass)
            && toolsRepository.equals(cacheKey.toolsRepository);
      }
    }

    @Override
    public int hashCode() {
      int result = fragmentClass.hashCode();
      result = 31 * result + toolsRepository.hashCode();
      return result;
    }
  }

  /**
   * A cache for efficient {@link SkylarkLateBoundDefault} loading by configuration fragment. Each
   * configuration fragment class key is mapped to a {@link Map} where keys are configuration field
   * skylark names, and values are the {@link SkylarkLateBoundDefault}s. Methods must be annotated
   * with {@link SkylarkConfigurationField} to be considered.
   */
  private static final LoadingCache<CacheKey, Map<String, SkylarkLateBoundDefault<?>>> fieldCache =
      CacheBuilder.newBuilder()
          .initialCapacity(10)
          .maximumSize(100)
          .build(
              new CacheLoader<CacheKey, Map<String, SkylarkLateBoundDefault<?>>>() {
                @Override
                public Map<String, SkylarkLateBoundDefault<?>> load(CacheKey key) throws Exception {
                  ImmutableMap.Builder<String, SkylarkLateBoundDefault<?>> lateBoundDefaultMap =
                      new ImmutableMap.Builder<>();
                  Class<?> fragmentClass = key.fragmentClass;
                  SkylarkModule fragmentModule =
                      SkylarkInterfaceUtils.getSkylarkModule(fragmentClass);

                  if (fragmentModule != null) {
                    for (Method method : fragmentClass.getMethods()) {
                      if (method.isAnnotationPresent(SkylarkConfigurationField.class)) {
                        // TODO(b/68817606): Use annotation processors to verify these constraints.
                        Preconditions.checkArgument(
                            method.getReturnType() == Label.class,
                            String.format("Method %s must have return type 'Label'", method));
                        Preconditions.checkArgument(
                            method.getParameterTypes().length == 0,
                            String.format("Method %s must not accept arguments", method));

                        SkylarkConfigurationField configField =
                            method.getAnnotation(SkylarkConfigurationField.class);
                        lateBoundDefaultMap.put(
                            configField.name(),
                            new SkylarkLateBoundDefault<>(
                                configField,
                                fragmentClass,
                                fragmentModule.name(),
                                method,
                                key.toolsRepository));
                      }
                    }
                  }
                  return lateBoundDefaultMap.build();
                }
              });

  /**
   * Returns a {@link LateBoundDefault} which obtains a late-bound attribute value (of type 'label')
   * specifically by skylark configuration fragment name and field name, as registered by {@link
   * SkylarkConfigurationField}.
   *
   * @param fragmentClass the configuration fragment class, which must have a valid skylark name
   * @param fragmentFieldName the configuration field name, as registered by {@link
   *     SkylarkConfigurationField} annotation
   * @param toolsRepository the Bazel tools repository path fragment
   * @throws InvalidConfigurationFieldException if there is no valid configuration field with the
   *     given fragment class and field name
   */
  @SuppressWarnings("unchecked")
  public static <FragmentT> SkylarkLateBoundDefault<FragmentT> forConfigurationField(
      Class<FragmentT> fragmentClass, String fragmentFieldName, String toolsRepository)
      throws InvalidConfigurationFieldException {
    try {
      CacheKey cacheKey = new CacheKey(fragmentClass, toolsRepository);
      SkylarkLateBoundDefault<?> resolver = fieldCache.get(cacheKey).get(fragmentFieldName);
      if (resolver == null) {
        SkylarkModule moduleAnnotation = SkylarkInterfaceUtils.getSkylarkModule(fragmentClass);
        if (moduleAnnotation == null) {
          throw new AssertionError("fragment class must have a valid Starlark name");
        }
        throw new InvalidConfigurationFieldException(
            String.format("invalid configuration field name '%s' on fragment '%s'",
                fragmentFieldName, moduleAnnotation.name()));
      }
      return (SkylarkLateBoundDefault<FragmentT>) resolver; // unchecked cast
    } catch (ExecutionException e) {
      throw new IllegalStateException("method invocation failed: " + e);
    }
  }

}
