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

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Interner;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.util.StringCanonicalizer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Function Signatures for BUILD language (same as Python)
 *
 * <p>Starlark's function signatures are just like Python3's. A function may have 6 kinds of
 * parameters: positional mandatory, positional optional, positional rest (aka *args or variadic
 * parameter), keyword-only mandatory, keyword-only optional, keyword rest (aka **kwargs parameter).
 * A caller may specify all arguments but the *args and **kwargs arguments by name, and thus all
 * mandatory and optional parameters are named parameters.
 *
 * <p>To enable various optimizations in the argument processing routine, we sort parameters
 * according the following constraints, enabling corresponding optimizations:
 *
 * <ol>
 *   <li>The positional mandatories come just before the positional optionals, so they can be filled
 *       in one go.
 *   <li>Positionals come first, so it's easy to prepend extra positional arguments such as "self"
 *       to an argument list, and we optimize for the common case of no key-only mandatory
 *       parameters. key-only parameters are thus grouped together. positional mandatory and
 *       key-only mandatory parameters are separate, but there is no loop over a contiguous chunk of
 *       them, anyway.
 *   <li>The named are all grouped together, with star and star_star rest parameters coming last.
 *   <li>Mandatory parameters in each category (positional and named-only) come before the optional
 *       parameters, for the sake of slightly better clarity to human implementers. This eschews an
 *       optimization whereby grouping optionals together allows to iterate over them in one go
 *       instead of two; however, this relatively minor optimization only matters when keyword
 *       arguments are passed, at which point it is dwarfed by the slowness of keyword processing.
 * </ol>
 *
 * <p>Parameters are thus sorted in the following order: positional mandatory parameters (if any),
 * positional optional parameters (if any), key-only mandatory parameters (if any), key-only
 * optional parameters (if any), then star parameter (if any), then star_star parameter (if any).
 */
@AutoCodec
@AutoValue
public abstract class FunctionSignature {

  // These abstract getters specify the actual parameter count fields to be defined by AutoValue.

  /** Number of mandatory positional parameters */
  public abstract int numMandatoryPositionals();

  /** Number of optional positional parameters */
  public abstract int numOptionalPositionals();

  /** Number of mandatory named-only parameters. */
  public abstract int numMandatoryNamedOnly();

  /** Number of optional named-only parameters */
  public abstract int numOptionalNamedOnly();

  /** True if function has variadic parameter, {@code def f(*args)}. */
  public abstract boolean hasVarargs();

  /** True if function has residual keyword-argument parameter, {@code def f(**kwargs)}. */
  public abstract boolean hasKwargs();

  /** Parameter names. */
  public abstract ImmutableList<String> getParameterNames();

  // computed parameter counts

  /** Number of optional and mandatory positional parameters. */
  public int numPositionals() {
    return numMandatoryPositionals() + numOptionalPositionals();
  }

  /** Number of optional and mandatory named-only parameters. */
  public int numNamedOnly() {
    return numMandatoryNamedOnly() + numOptionalNamedOnly();
  }

  /** number of optional parameters. */
  public int numOptionals() {
    return numOptionalPositionals() + numOptionalNamedOnly();
  }

  /** number of all named parameters: mandatory and optional of positionals and named-only */
  public int numAllNamed() {
    return numPositionals() + numNamedOnly();
  }

  /** total number of parameters */
  public int numParameters() {
    return numAllNamed() + (hasVarargs() ? 1 : 0) + (hasKwargs() ? 1 : 0);
  }

  private static final Interner<ImmutableList<String>> namesInterner =
      BlazeInterners.newWeakInterner();

  /** Intern a list of names. */
  private static ImmutableList<String> names(List<String> names) {
    return namesInterner.intern(
        names.stream().map(StringCanonicalizer::intern).collect(toImmutableList()));
  }

  // Interner.
  // Are there really a significant number of duplicates? Why??
  private static final Interner<FunctionSignature> signatureInterner =
      BlazeInterners.newWeakInterner();

  // TODO(adonovan): not a user-friendly API. Provide external callers with this function:
  //   FunctionSignature.parse("a, b=1, *, c, d=2, *args, **kwargs")
  // implemented by invoking the Starlark parser. (Most uses are in tests.)
  @AutoCodec.Instantiator
  public static FunctionSignature create(
      int numMandatoryPositionals,
      int numOptionalPositionals,
      int numMandatoryNamedOnly,
      int numOptionalNamedOnly,
      boolean hasVarargs,
      boolean hasKwargs,
      ImmutableList<String> parameterNames) {
    Preconditions.checkArgument(
        0 <= numMandatoryPositionals
            && 0 <= numOptionalPositionals
            && 0 <= numMandatoryNamedOnly
            && 0 <= numOptionalNamedOnly);

    FunctionSignature sig =
        new AutoValue_FunctionSignature(
            numMandatoryPositionals,
            numOptionalPositionals,
            numMandatoryNamedOnly,
            numOptionalNamedOnly,
            hasVarargs,
            hasKwargs,
            names(parameterNames));

    Preconditions.checkArgument(parameterNames.size() == sig.numParameters());
    return signatureInterner.intern(sig);
  }

  @Override
  public final String toString() {
    StringBuilder sb = new StringBuilder();
    toStringBuilder(sb, null); // no default values
    return sb.toString();
  }

  // ElementPrinter returns the string form of the ith element of a sequence.
  interface ElementPrinter {
    String print(int i);
  }

  /**
   * Appends a representation of this signature to a string buffer.
   *
   * @param printer output StringBuilder
   * @param defaultValuePrinter optional callback for formatting i'th default value (if any).
   */
  StringBuilder toStringBuilder(
      final StringBuilder printer, @Nullable final ElementPrinter defaultValuePrinter) {
    final ImmutableList<String> names = getParameterNames();

    int mandatoryPositionals = numMandatoryPositionals();
    int optionalPositionals = numOptionalPositionals();
    int mandatoryNamedOnly = numMandatoryNamedOnly();
    int optionalNamedOnly = numOptionalNamedOnly();
    boolean hasVarargs = hasVarargs();
    boolean hasKwargs = hasKwargs();
    int positionals = mandatoryPositionals + optionalPositionals;
    int namedOnly = mandatoryNamedOnly + optionalNamedOnly;
    int named = positionals + namedOnly;
    int args = named + (hasVarargs ? 1 : 0) + (hasKwargs ? 1 : 0);
    int endMandatoryNamedOnly = positionals + mandatoryNamedOnly;
    boolean hasStar = hasVarargs || (namedOnly > 0);
    int iStarArg = named;
    int iKwArg = args - 1;

    class Show {
      private boolean isMore = false;
      private int j = 0;

      public void comma() {
        if (isMore) {
          printer.append(", ");
        }
        isMore = true;
      }

      public void mandatory(int i) {
        comma();
        printer.append(names.get(i));
      }

      public void optional(int i) {
        mandatory(i);
        if (defaultValuePrinter != null) {
          String str = defaultValuePrinter.print(j++);
          printer.append(" = ").append(str != null ? str : "?");
        }
      }
    }

    Show show = new Show();

    int i = 0;
    for (; i < mandatoryPositionals; i++) {
      show.mandatory(i);
    }
    for (; i < positionals; i++) {
      show.optional(i);
    }
    if (hasStar) {
      show.comma();
      printer.append("*");
      if (hasVarargs) {
        printer.append(names.get(iStarArg));
      }
    }
    for (; i < endMandatoryNamedOnly; i++) {
      show.mandatory(i);
    }
    for (; i < named; i++) {
      show.optional(i);
    }
    if (hasKwargs) {
      show.comma();
      printer.append("**");
      printer.append(names.get(iKwArg));
    }

    return printer;
  }

  /** Convert a list of Parameter into a FunctionSignature. */
  static FunctionSignature fromParameters(Iterable<Parameter> parameters)
      throws SignatureException {
    int mandatoryPositionals = 0;
    int optionalPositionals = 0;
    int mandatoryNamedOnly = 0;
    int optionalNamedOnly = 0;
    boolean hasStarStar = false;
    boolean hasStar = false;
    @Nullable String star = null;
    @Nullable String starStar = null;
    ArrayList<String> params = new ArrayList<>();
    // optional named-only parameters are kept aside to be spliced after the mandatory ones.
    ArrayList<String> optionalNamedOnlyParams = new ArrayList<>();
    boolean defaultRequired = false; // true after mandatory positionals and before star.
    Set<String> paramNameSet = new HashSet<>(); // set of names, to avoid duplicates

    for (Parameter param : parameters) {
      if (hasStarStar) {
        throw new SignatureException("illegal parameter after star-star parameter", param);
      }
      @Nullable String name = param.getName();
      if (param.getName() != null) {
        if (paramNameSet.contains(name)) {
          throw new SignatureException("duplicate parameter name in function definition", param);
        }
        paramNameSet.add(name);
      }
      if (param instanceof Parameter.StarStar) {
        hasStarStar = true;
        starStar = name;
      } else if (param instanceof Parameter.Star) {
        if (hasStar) {
          throw new SignatureException("duplicate star parameter in function definition", param);
        }
        hasStar = true;
        defaultRequired = false;
        if (param.getName() != null) {
          star = name;
        }
      } else if (hasStar && param instanceof Parameter.Optional) {
        optionalNamedOnly++;
        optionalNamedOnlyParams.add(name);
      } else {
        params.add(name);
        if (param instanceof Parameter.Optional) {
          optionalPositionals++;
          defaultRequired = true;
        } else if (hasStar) {
          mandatoryNamedOnly++;
        } else if (defaultRequired) {
          throw new SignatureException(
              "a mandatory positional parameter must not follow an optional parameter", param);
        } else {
          mandatoryPositionals++;
        }
      }
    }
    params.addAll(optionalNamedOnlyParams);

    if (star != null) {
      params.add(star);
    }
    if (starStar != null) {
      params.add(starStar);
    }
    return FunctionSignature.create(
        mandatoryPositionals,
        optionalPositionals,
        mandatoryNamedOnly,
        optionalNamedOnly,
        star != null,
        starStar != null,
        ImmutableList.copyOf(params));
  }

  /**
   * Constructs a function signature (with names) from signature description and names. This method
   * covers the general case. The number of optional named-only parameters is deduced from the other
   * arguments.
   *
   * @param numMandatoryPositionals an int for the number of mandatory positional parameters
   * @param numOptionalPositionals an int for the number of optional positional parameters
   * @param numMandatoryNamedOnly an int for the number of mandatory named-only parameters
   * @param hasVarargs whether function is variadic parameter
   * @param hasKwargs whether function accepts arbitrary named arguments
   * @param names an Array of String for the parameter names
   */
  static FunctionSignature of(
      int numMandatoryPositionals,
      int numOptionalPositionals,
      int numMandatoryNamedOnly,
      boolean hasVarargs,
      boolean hasKwargs,
      String... names) {
    return create(
        numMandatoryPositionals,
        numOptionalPositionals,
        numMandatoryNamedOnly,
        names.length
            - (hasKwargs ? 1 : 0)
            - (hasVarargs ? 1 : 0)
            - numMandatoryPositionals
            - numOptionalPositionals
            - numMandatoryNamedOnly,
        hasVarargs,
        hasKwargs,
        ImmutableList.copyOf(names));
  }

  /**
   * Constructs a function signature from mandatory positional argument names.
   *
   * @param names an Array of String for the positional parameter names
   * @return a FunctionSignature
   */
  public static FunctionSignature of(String... names) {
    return of(names.length, 0, 0, false, false, names);
  }

  /**
   * Constructs a function signature from positional argument names.
   *
   * @param numMandatory an int for the number of mandatory positional parameters
   * @param names an Array of String for the positional parameter names
   * @return a FunctionSignature
   */
  public static FunctionSignature of(int numMandatory, String... names) {
    return of(numMandatory, names.length - numMandatory, 0, false, false, names);
  }

  /**
   * Constructs a function signature from named-only parameter names.
   *
   * @param numMandatory an int for the number of mandatory named-only parameters
   * @param names an Array of String for the named-only parameter names
   * @return a FunctionSignature
   */
  public static FunctionSignature namedOnly(int numMandatory, String... names) {
    return of(0, 0, numMandatory, false, false, names);
  }

  /** Invalid signature from Parser or from SkylarkCallable annotation. */
  static class SignatureException extends Exception {
    private final Parameter parameter;

    /** SignatureException from a message and a Parameter */
    SignatureException(String message, Parameter parameter) {
      super(message);
      this.parameter = parameter;
    }

    /** Returns the parameter that caused the exception. */
    Parameter getParameter() {
      return parameter;
    }
  }

  /** A ready-made signature to allow only keyword parameters and put them in a kwarg parameter */
  public static final FunctionSignature KWARGS =
      FunctionSignature.of(0, 0, 0, false, true, "kwargs");

  /** A ready-made signature that allows any arguments. */
  public static final FunctionSignature ANY =
      FunctionSignature.of(0, 0, 0, true, true, "args", "kwargs");
}
