// Copyright 2018 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.syntax;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.util.SpellChecker;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import javax.annotation.Nullable;

/**
 * A BuiltinCallable is a callable Starlark value that reflectively invokes a
 * SkylarkCallable-annotated method of a Java object.
 */
// TODO(adonovan): make this private. Most users would be content with StarlarkCallable; the rest
// need only a means of querying the function's parameters.
public final class BuiltinCallable implements StarlarkCallable {

  private final Object obj;
  private final String methodName;
  @Nullable private final MethodDescriptor desc;

  /**
   * Constructs a BuiltinCallable for a StarlarkCallable-annotated method of the given name (as seen
   * by Starlark, not Java).
   */
  // TODO(adonovan): eliminate calls to this constructor from tests; use getattr instead.
  BuiltinCallable(Object obj, String methodName) {
    this(obj, methodName, /*desc=*/ null);
  }

  /**
   * Constructs a BuiltinCallable for a StarlarkCallable-annotated method of the given name (as seen
   * by Starlark, not Java).
   *
   * <p>This constructor should be used only for ephemeral BuiltinCallable values created
   * transiently during a call such as {@code x.f()}, when the caller has already looked up the
   * MethodDescriptor using the same semantics as the thread that will be used in the call. Use the
   * other (slower) constructor if there is any possibility that the semantics of the {@code x.f}
   * operation differ from those of the thread used in the call.
   */
  BuiltinCallable(Object obj, String methodName, MethodDescriptor desc) {
    this.obj = obj;
    this.methodName = methodName;
    this.desc = desc;
  }

  @Override
  public Object fastcall(StarlarkThread thread, Object[] positional, Object[] named)
      throws EvalException, InterruptedException {
    MethodDescriptor desc =
        this.desc != null ? this.desc : getMethodDescriptor(thread.getSemantics());
    Preconditions.checkArgument(
        !desc.isStructField(),
        "struct field methods should be handled by DotExpression separately");
    Object[] vector = getArgumentVector(thread, desc, positional, named);
    return desc.call(
        obj instanceof String ? StringModule.INSTANCE : obj, vector, thread.mutability());
  }

  private MethodDescriptor getMethodDescriptor(StarlarkSemantics semantics) {
    return CallUtils.getMethod(semantics, obj.getClass(), methodName);
  }

  /**
   * Returns the SkylarkCallable annotation of this Starlark-callable Java method.
   *
   * @deprecated This method is intended only for docgen, and uses the default semantics.
   */
  @Deprecated
  public SkylarkCallable getAnnotation() {
    return getMethodDescriptor(StarlarkSemantics.DEFAULT_SEMANTICS).getAnnotation();
  }

  @Override
  public String getName() {
    return methodName;
  }

  @Override
  public void repr(Printer printer) {
    printer.append("<built-in function " + methodName + ">");
  }

  @Override
  public String toString() {
    return methodName;
  }

  /**
   * Converts the arguments of a Starlark call into the argument vector for a reflective call to a
   * SkylarkCallable-annotated Java method.
   *
   * @param thread the Starlark thread for the call
   * @param loc the location of the call expression, or BUILTIN for calls from Java
   * @param desc descriptor for the StarlarkCallable-annotated method
   * @param positional a list of positional arguments
   * @param named a list of named arguments, as alternating Strings/Objects. May contain dups.
   * @return the array of arguments which may be passed to {@link MethodDescriptor#call}
   * @throws EvalException if the given set of arguments are invalid for the given method. For
   *     example, if any arguments are of unexpected type, or not all mandatory parameters are
   *     specified by the user
   */
  private Object[] getArgumentVector(
      StarlarkThread thread,
      MethodDescriptor desc, // intentionally shadows this.desc
      Object[] positional,
      Object[] named)
      throws EvalException {

    // Overview of steps:
    // - allocate vector of actual arguments of correct size.
    // - process positional arguments, accumulating surplus ones into *args.
    // - process named arguments, accumulating surplus ones into **kwargs.
    // - set default values for missing optionals, and report missing mandatory parameters.
    // - set special parameters.
    // The static checks ensure that positional parameters appear before named,
    // and mandatory positionals appear before optional.
    // No additional memory allocation occurs in the common (success) case.
    // Flag-disabled parameters are skipped during argument matching, as if they do not exist. They
    // are instead assigned their flag-disabled values.

    ParamDescriptor[] parameters = desc.getParameters();

    // Allocate argument vector.
    int n = parameters.length;
    if (desc.acceptsExtraArgs()) {
      n++;
    }
    if (desc.acceptsExtraKwargs()) {
      n++;
    }
    if (desc.isUseStarlarkThread()) {
      n++;
    }
    Object[] vector = new Object[n];

    // positional arguments
    int paramIndex = 0;
    int argIndex = 0;
    if (obj instanceof String) {
      // String methods get the string as an extra argument
      // because their true receiver is StringModule.INSTANCE.
      vector[paramIndex++] = obj;
    }
    for (; argIndex < positional.length && paramIndex < parameters.length; paramIndex++) {
      ParamDescriptor param = parameters[paramIndex];
      if (!param.isPositional()) {
        break;
      }

      // disabled?
      if (param.disabledByFlag() != null) {
        // Skip disabled parameter as if not present at all.
        // The default value will be filled in below.
        continue;
      }

      Object value = positional[argIndex++];
      checkParamValue(param, value);
      vector[paramIndex] = value;
    }

    // *args
    Tuple<Object> varargs = null;
    if (desc.acceptsExtraArgs()) {
      varargs = Tuple.wrap(Arrays.copyOfRange(positional, argIndex, positional.length));
    } else if (argIndex < positional.length) {
      if (argIndex == 0) {
        throw Starlark.errorf("%s() got unexpected positional argument", methodName);
      } else {
        throw Starlark.errorf(
            "%s() accepts no more than %d positional argument%s but got %d",
            methodName, argIndex, plural(argIndex), positional.length);
      }
    }

    // named arguments
    LinkedHashMap<String, Object> kwargs = desc.acceptsExtraKwargs() ? new LinkedHashMap<>() : null;
    for (int i = 0; i < named.length; i += 2) {
      String name = (String) named[i]; // safe
      Object value = named[i + 1];

      // look up parameter
      int index = desc.getParameterIndex(name);
      // unknown parameter?
      if (index < 0) {
        // spill to **kwargs
        if (kwargs == null) {
          List<String> allNames =
              Arrays.stream(parameters)
                  .map(ParamDescriptor::getName)
                  .collect(ImmutableList.toImmutableList());
          throw Starlark.errorf(
              "%s() got unexpected keyword argument '%s'%s",
              methodName, name, SpellChecker.didYouMean(name, allNames));
        }

        // duplicate named argument?
        if (kwargs.put(name, value) != null) {
          throw Starlark.errorf(
              "%s() got multiple values for keyword argument '%s'", methodName, name);
        }
        continue;
      }
      ParamDescriptor param = parameters[index];

      // positional-only param?
      if (!param.isNamed()) {
        // spill to **kwargs
        if (kwargs == null) {
          throw Starlark.errorf(
              "%s() got named argument for positional-only parameter '%s'", methodName, name);
        }

        // duplicate named argument?
        if (kwargs.put(name, value) != null) {
          throw Starlark.errorf(
              "%s() got multiple values for keyword argument '%s'", methodName, name);
        }
        continue;
      }

      // disabled?
      String flag = param.disabledByFlag();
      if (flag != null) {
        // spill to **kwargs
        if (kwargs == null) {
          throw Starlark.errorf(
              "in call to %s(), parameter '%s' is %s",
              methodName, param.getName(), disabled(flag, thread.getSemantics()));
        }

        // duplicate named argument?
        if (kwargs.put(name, value) != null) {
          throw Starlark.errorf(
              "%s() got multiple values for keyword argument '%s'", methodName, name);
        }
        continue;
      }

      checkParamValue(param, value);

      // duplicate?
      if (vector[index] != null) {
        throw Starlark.errorf("%s() got multiple values for argument '%s'", methodName, name);
      }

      vector[index] = value;
    }

    // Set default values for missing parameters,
    // and report any that are still missing.
    List<String> missingPositional = null;
    List<String> missingNamed = null;
    for (int i = 0; i < parameters.length; i++) {
      if (vector[i] == null) {
        ParamDescriptor param = parameters[i];
        vector[i] = param.getDefaultValue();
        if (vector[i] == null) {
          if (param.isPositional()) {
            if (missingPositional == null) {
              missingPositional = new ArrayList<>();
            }
            missingPositional.add(param.getName());
          } else {
            if (missingNamed == null) {
              missingNamed = new ArrayList<>();
            }
            missingNamed.add(param.getName());
          }
        }
      }
    }
    if (missingPositional != null) {
      throw Starlark.errorf(
          "%s() missing %d required positional argument%s: %s",
          methodName,
          missingPositional.size(),
          plural(missingPositional.size()),
          Joiner.on(", ").join(missingPositional));
    }
    if (missingNamed != null) {
      throw Starlark.errorf(
          "%s() missing %d required named argument%s: %s",
          methodName,
          missingNamed.size(),
          plural(missingNamed.size()),
          Joiner.on(", ").join(missingNamed));
    }

    // special parameters
    int i = parameters.length;
    if (desc.acceptsExtraArgs()) {
      vector[i++] = varargs;
    }
    if (desc.acceptsExtraKwargs()) {
      vector[i++] = Dict.wrap(thread.mutability(), kwargs);
    }
    if (desc.isUseStarlarkThread()) {
      vector[i++] = thread;
    }

    return vector;
  }

  private static String plural(int n) {
    return n == 1 ? "" : "s";
  }

  private void checkParamValue(ParamDescriptor param, Object value) throws EvalException {
    // invalid argument?
    SkylarkType type = param.getSkylarkType();
    if (!type.contains(value)) {
      throw Starlark.errorf(
          "in call to %s(), parameter '%s' got value of type '%s', want '%s'",
          methodName, param.getName(), EvalUtils.getDataTypeName(value), type);
    }

    // unexpected None?
    if (value == Starlark.NONE && !param.isNoneable()) {
      throw Starlark.errorf(
          "in call to %s(), parameter '%s' cannot be None", methodName, param.getName());
    }
  }

  // Returns a phrase meaning "disabled" appropriate to the specified flag.
  private static String disabled(String flag, StarlarkSemantics semantics) {
    // If the flag is True, it must be a deprecation flag. Otherwise it's an experimental flag.
    // TODO(adonovan): is that assumption sound?
    if (semantics.flagValue(flag)) {
      return String.format(
          "deprecated and will be removed soon. It may be temporarily re-enabled by setting"
              + " --%s=false",
          flag);
    } else {
      return String.format(
          "experimental and thus unavailable with the current flags. It may be enabled by setting"
              + " --%s",
          flag);
    }
  }
}
