// 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.packages;

import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.syntax.BaseFunction;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.FunctionSignature;
import com.google.devtools.build.lib.syntax.SkylarkType;
import javax.annotation.Nullable;

/**
 * Declared Provider (a constructor for {@link Info}).
 *
 * <p>Declared providers can be declared either natively ({@link NativeProvider} or in Skylark
 * {@link SkylarkProvider}.
 *
 * <p>{@link Provider} serves both as "type identifier" for declared provider instances and as a
 * function that can be called to construct a provider.
 *
 * <p>Prefer to use {@link Key} as a serializable identifier of {@link Provider}. In particular,
 * {@link Key} should be used in all data structures exposed to Skyframe.
 */
@SkylarkModule(
  name = "Provider",
  doc =
      "A constructor for simple value objects, known as provider instances."
          + "<br>"
          + "This value has a dual purpose:"
          + "  <ul>"
          + "     <li>It is a function that can be called to construct 'struct'-like values:"
          + "<pre class=\"language-python\">DataInfo = provider()\n"
          + "d = DataInfo(x = 2, y = 3)\n"
          + "print(d.x + d.y) # prints 5</pre>"
          + "     Note: Some providers, defined internally, do not allow instance creation"
          + "     </li>"
          + "     <li>It is a <i>key</i> to access a provider instance on a"
          + "        <a href=\"Target.html\">Target</a>"
          + "<pre class=\"language-python\">DataInfo = provider()\n"
          + "def _rule_impl(ctx)\n"
          + "  ... ctx.attr.dep[DataInfo]</pre>"
          + "     </li>"
          + "  </ul>"
          + "Create a new <code>Provider</code> using the "
          + "<a href=\"globals.html#provider\">provider</a> function."
)
@Immutable
public abstract class Provider extends BaseFunction {

  protected Provider(
      String name, FunctionSignature.WithValues<Object, SkylarkType> signature, Location location) {
    super(name, signature, location);
  }

  /**
   * Has this {@link Provider} been exported? All native providers are always exported. Skylark
   * providers are exported if they are assigned to top-level name in a Skylark module.
   */
  public abstract boolean isExported();

  /** Returns a serializable representation of this {@link Provider}. */
  public abstract Key getKey();

  /** Returns a name of this {@link Provider} that should be used in error messages. */
  public abstract String getPrintableName();

  /**
   * Returns an error message format for instances.
   *
   * <p>Must contain one '%s' placeholder for field name.
   */
  public abstract String getErrorMessageFormatForInstances();

  public SkylarkProviderIdentifier id() {
    return SkylarkProviderIdentifier.forKey(getKey());
  }

  @Override
  protected Object call(Object[] args, @Nullable FuncallExpression ast, @Nullable Environment env)
      throws EvalException, InterruptedException {
    Location loc = ast != null ? ast.getLocation() : Location.BUILTIN;
    return createInstanceFromSkylark(args, loc);
  }

  /**
   * Override this method to provide logic that is used to instantiate a declared provider from
   * Skylark.
   *
   * <p>This is a method that is called when a constructor {@code c} is invoked as<br>
   * {@code c(arg1 = val1, arg2 = val2, ...)}.
   *
   * @param args an array of argument values sorted as per the signature ({@see BaseFunction#call})
   */
  protected abstract Info createInstanceFromSkylark(Object[] args, Location loc)
      throws EvalException;

  /** A serializable representation of {@link Provider}. */
  public abstract static class Key {}
}
