// 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.build.docgen;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.docgen.skylark.SkylarkBuiltinMethodDoc;
import com.google.devtools.build.docgen.skylark.SkylarkConstructorMethodDoc;
import com.google.devtools.build.docgen.skylark.SkylarkJavaMethodDoc;
import com.google.devtools.build.docgen.skylark.SkylarkModuleDoc;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
import com.google.devtools.build.lib.syntax.CallUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.Nullable;

/**
 * A helper class that collects Skylark module documentation.
 */
final class SkylarkDocumentationCollector {
  @SkylarkModule(
    name = "globals",
    title = "Globals",
    category = SkylarkModuleCategory.TOP_LEVEL_TYPE,
    doc = "Objects, functions and modules registered in the global environment."
  )
  private static final class TopLevelModule {}

  private SkylarkDocumentationCollector() {}

  /**
   * Returns the SkylarkModule annotation for the top-level Skylark module.
   */
  public static SkylarkModule getTopLevelModule() {
    return TopLevelModule.class.getAnnotation(SkylarkModule.class);
  }

  /**
   * Collects the documentation for all Skylark modules comprised of the given classes and returns a
   * map that maps Skylark module name to the module documentation.
   */
  public static Map<String, SkylarkModuleDoc> collectModules(Iterable<Class<?>> classes) {
    Map<String, SkylarkModuleDoc> modules = new TreeMap<>();
    // The top level module first.
    // (This is a special case of {@link SkylarkModuleDoc} as it has no object name).
    SkylarkModule topLevelModule = getTopLevelModule();
    modules.put(topLevelModule.name(), new SkylarkModuleDoc(topLevelModule, TopLevelModule.class));

    // Creating module documentation is done in three passes.
    // 1. Add all classes/interfaces annotated with @SkylarkModule with documented = true.
    for (Class<?> candidateClass : classes) {
      if (candidateClass.isAnnotationPresent(SkylarkModule.class)) {
        collectSkylarkModule(candidateClass, modules);
      }
    }

    // 2. Add all object methods and global functions.
    for (Class<?> candidateClass : classes) {
      if (candidateClass.isAnnotationPresent(SkylarkModule.class)) {
        collectModuleMethods(candidateClass, modules);
      }
      if (candidateClass.isAnnotationPresent(SkylarkGlobalLibrary.class)) {
        collectGlobalLibraryMethods(candidateClass, modules);
      }
      // Use of SkylarkSignature fields is deprecated, but not all uses have been migrated.
      collectSkylarkSignatureFunctions(candidateClass, modules);
    }

    // 3. Add all constructors.
    for (Class<?> candidateClass : classes) {
      if (candidateClass.isAnnotationPresent(SkylarkModule.class)
          || candidateClass.isAnnotationPresent(SkylarkGlobalLibrary.class)) {
        collectConstructorMethods(candidateClass, modules);
      }
    }

    return modules;
  }

  /**
   * Returns the {@link SkylarkModuleDoc} entry representing the collection of top level functions.
   * (This is a special case of {@link SkylarkModuleDoc} as it has no object name).
   */
  private static SkylarkModuleDoc getTopLevelModuleDoc(Map<String, SkylarkModuleDoc> modules) {
    return modules.get(getTopLevelModule().name());
  }

  /**
   * Adds a single {@link SkylarkModuleDoc} entry to {@code modules} representing the given {@code
   * moduleClass}, if it is a documented module.
   */
  private static void collectSkylarkModule(
      Class<?> moduleClass, Map<String, SkylarkModuleDoc> modules) {
    if (moduleClass.equals(TopLevelModule.class)) {
      // The top level module doc is a special case and is handled separately.
      return;
    }

    SkylarkModule moduleAnnotation =
        Preconditions.checkNotNull(moduleClass.getAnnotation(SkylarkModule.class));

    if (moduleAnnotation.documented()) {
      SkylarkModuleDoc previousModuleDoc = modules.get(moduleAnnotation.name());
      if (previousModuleDoc == null) {
        modules.put(moduleAnnotation.name(), new SkylarkModuleDoc(moduleAnnotation, moduleClass));
      } else {
        // Handle a strange corner-case: If moduleClass has a subclass which is also
        // annotated with @SkylarkModule with the same name, and also has the same module-level
        // docstring, then the subclass takes precedence.
        // (This is useful if one module is a "common" stable module, and its subclass is
        // an experimental module that also supports all stable methods.)
        validateCompatibleModules(previousModuleDoc.getClassObject(), moduleClass);

        if (previousModuleDoc.getClassObject().isAssignableFrom(moduleClass)) {
          // The new module is a subclass of the old module, so use the subclass.
          modules.put(moduleAnnotation.name(), new SkylarkModuleDoc(moduleAnnotation, moduleClass));
        }
      }
    }
  }

  /**
   * Validate that it is acceptable that the given module classes with the same module name
   * co-exist.
   */
  private static void validateCompatibleModules(Class<?> one, Class<?> two) {
    SkylarkModule moduleOne = one.getAnnotation(SkylarkModule.class);
    SkylarkModule moduleTwo = two.getAnnotation(SkylarkModule.class);
    if (one.isAssignableFrom(two) || two.isAssignableFrom(one)) {
      if (!moduleOne.doc().equals(moduleTwo.doc())) {
        throw new IllegalStateException(
            String.format(
                "%s and %s are related modules but have mismatching documentation for '%s'",
                one, two, moduleOne.name()));
      }
    } else {
      throw new IllegalStateException(
          String.format(
              "%s and %s are unrelated modules with documentation for '%s'",
              one, two, moduleOne.name()));
    }
  }

  private static void collectModuleMethods(
      Class<?> moduleClass, Map<String, SkylarkModuleDoc> modules) {
    SkylarkModule moduleAnnotation =
        Preconditions.checkNotNull(moduleClass.getAnnotation(SkylarkModule.class));

    if (moduleAnnotation.documented()) {
      SkylarkModuleDoc moduleDoc = Preconditions.checkNotNull(modules.get(moduleAnnotation.name()));

      if (moduleClass == moduleDoc.getClassObject()) {
        ImmutableMap<Method, SkylarkCallable> methods =
            CallUtils.collectSkylarkMethodsWithAnnotation(moduleClass);
        for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
          // Only collect methods not annotated with @SkylarkConstructor. Methods with
          // @SkylarkConstructor are added later.
          if (!entry.getKey().isAnnotationPresent(SkylarkConstructor.class)) {
            moduleDoc.addMethod(
                new SkylarkJavaMethodDoc(moduleDoc.getName(), entry.getKey(), entry.getValue()));
          }
        }
      }
    }
  }

  @Nullable
  private static Map.Entry<Method, SkylarkCallable> getSelfCallConstructorMethod(
      Class<?> objectClass) {
    ImmutableMap<Method, SkylarkCallable> methods =
        CallUtils.collectSkylarkMethodsWithAnnotation(objectClass);
    for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
      if (entry.getValue().selfCall()
          && entry.getKey().isAnnotationPresent(SkylarkConstructor.class)) {
        // It's illegal, and checked by the interpreter, for there to be more than one method
        // annotated with selfCall. Thus, it's valid to return on the first find.
        return entry;
      }
    }
    return null;
  }

  /**
   * Adds {@link SkylarkJavaMethodDoc} entries to the top level module, one for
   * each @SkylarkCallable method defined in the given @SkylarkGlobalLibrary class {@code
   * moduleClass}.
   */
  private static void collectGlobalLibraryMethods(
      Class<?> moduleClass, Map<String, SkylarkModuleDoc> modules) {
    Preconditions.checkArgument(moduleClass.isAnnotationPresent(SkylarkGlobalLibrary.class));
    SkylarkModuleDoc topLevelModuleDoc = getTopLevelModuleDoc(modules);

    ImmutableMap<Method, SkylarkCallable> methods =
        CallUtils.collectSkylarkMethodsWithAnnotation(moduleClass);
    for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
      // Only add non-constructor global library methods. Constructors are added later.
      if (!entry.getKey().isAnnotationPresent(SkylarkConstructor.class)) {
        topLevelModuleDoc.addMethod(new SkylarkJavaMethodDoc("", entry.getKey(), entry.getValue()));
      }
    }
  }

  /**
   * Adds {@link SkylarkBuiltinMethodDoc} entries to the top level module, one for
   * each @SkylarkSignature-annotated field defined in the given {@code moduleClass}.
   *
   * <p>Note that use of SkylarkSignature fields is deprecated, but not all uses have been migrated.
   */
  private static void collectSkylarkSignatureFunctions(
      Class<?> moduleClass, Map<String, SkylarkModuleDoc> modules) {

    SkylarkModuleDoc topLevelModuleDoc = getTopLevelModuleDoc(modules);

    // Collect any fields annotated with @SkylarkSignature, even if the class isn't
    // annotated.
    for (Field field : moduleClass.getDeclaredFields()) {
      if (field.isAnnotationPresent(SkylarkSignature.class)) {
        SkylarkSignature skylarkSignature = field.getAnnotation(SkylarkSignature.class);
        Preconditions.checkState(skylarkSignature.objectType() == Object.class);

        topLevelModuleDoc.addMethod(
            new SkylarkBuiltinMethodDoc(
                getTopLevelModuleDoc(modules), skylarkSignature, field.getType()));
      }
    }
  }

  private static void collectConstructor(
      Map<String, SkylarkModuleDoc> modules,
      Class<?> moduleClass,
      Method method,
      SkylarkCallable callable) {
    SkylarkConstructor constructorAnnotation =
        Preconditions.checkNotNull(method.getAnnotation(SkylarkConstructor.class));
    Class<?> objectClass = constructorAnnotation.objectType();
    SkylarkModule objectModule = objectClass.getAnnotation(SkylarkModule.class);
    if (objectModule == null || !objectModule.documented()) {
      // The class of the constructed object type has no documentation, so no place to add
      // constructor information.
      return;
    }
    SkylarkModuleDoc module = modules.get(objectModule.name());

    String fullyQualifiedName;
    if (!constructorAnnotation.receiverNameForDoc().isEmpty()) {
      fullyQualifiedName = constructorAnnotation.receiverNameForDoc();
    } else {
      String originatingModuleName = getModuleNameForConstructorPrefix(moduleClass, modules);
      fullyQualifiedName = getFullyQualifiedName(originatingModuleName, callable);
    }

    module.setConstructor(new SkylarkConstructorMethodDoc(fullyQualifiedName, method, callable));
  }

  /**
   * Collect two types of constructor methods:
   *
   * <p>1. Methods that are annotated with @SkylarkConstructor.
   *
   * <p>2. Structfield methods that return an object which itself has a method with selfCall = true,
   * and is annotated with @SkylarkConstructor. (For example, suppose Foo has a structfield method
   * 'bar'. If Foo.bar is itself callable, and is a constructor, then Foo.bar() should be treated
   * like a constructor method.)
   */
  private static void collectConstructorMethods(
      Class<?> moduleClass, Map<String, SkylarkModuleDoc> modules) {

    ImmutableMap<Method, SkylarkCallable> methods =
        CallUtils.collectSkylarkMethodsWithAnnotation(moduleClass);
    for (Map.Entry<Method, SkylarkCallable> entry : methods.entrySet()) {
      if (entry.getKey().isAnnotationPresent(SkylarkConstructor.class)) {
        collectConstructor(modules, moduleClass, entry.getKey(), entry.getValue());
      }
      Class<?> returnClass = entry.getKey().getReturnType();
      Map.Entry<Method, SkylarkCallable> selfCallConstructor =
          getSelfCallConstructorMethod(returnClass);
      if (selfCallConstructor != null) {
        collectConstructor(
            modules, moduleClass, selfCallConstructor.getKey(), selfCallConstructor.getValue());
      }
    }
  }

  private static String getModuleNameForConstructorPrefix(
      Class<?> moduleClass, Map<String, SkylarkModuleDoc> modules) {
    if (moduleClass.isAnnotationPresent(SkylarkModule.class)) {
      String moduleName = moduleClass.getAnnotation(SkylarkModule.class).name();
      SkylarkModuleDoc moduleDoc = Preconditions.checkNotNull(modules.get(moduleName));

      if (moduleClass != moduleDoc.getClassObject()) {
        throw new IllegalStateException(
            "Could not determine module name for constructor defined in " + moduleClass);
      }
      return moduleName;
    } else if (moduleClass.isAnnotationPresent(SkylarkGlobalLibrary.class)) {
      return "";
    } else {
      throw new IllegalArgumentException(moduleClass + " has no valid annotation");
    }
  }

  private static String getFullyQualifiedName(
      String objectName, SkylarkCallable callable) {
    String objectDotExpressionPrefix = objectName.isEmpty() ? "" : objectName + ".";
    String methodName = callable.name();
    return objectDotExpressionPrefix + methodName;
  }
}
