// 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.rules.python;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.packages.StructProvider;
import com.google.devtools.build.lib.syntax.Depset;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.SkylarkType;

/** Static helper class for creating and accessing instances of the legacy "py" struct provider. */
// TODO(#7010): Remove this in favor of PyInfo.
public class PyStructUtils {

  // Disable construction.
  private PyStructUtils() {}

  /** Name of the Python provider in Starlark code (as a field of a {@code Target}. */
  public static final String PROVIDER_NAME = "py";

  /**
   * Name of field holding a postorder-compatible depset of transitive sources (i.e., .py files in
   * {@code srcs} and in {@code srcs} of transitive {@code deps}).
   */
  public static final String TRANSITIVE_SOURCES = "transitive_sources";

  /**
   * Name of field holding a boolean indicating whether any transitive dep uses shared libraries.
   */
  public static final String USES_SHARED_LIBRARIES = "uses_shared_libraries";

  /**
   * Name of field holding a depset of import paths added by the transitive deps (including this
   * target).
   */
  // TODO(brandjon): Make this a pre-order depset, since higher-level targets should get precedence
  // on PYTHONPATH. Add assertions on its order compatibility.
  public static final String IMPORTS = "imports";

  /**
   * Name of field holding a boolean indicating whether there are any transitive sources that
   * require a Python 2 runtime.
   */
  public static final String HAS_PY2_ONLY_SOURCES = "has_py2_only_sources";

  /**
   * Name of field holding a boolean indicating whether there are any transitive sources that
   * require a Python 3 runtime.
   */
  public static final String HAS_PY3_ONLY_SOURCES = "has_py3_only_sources";

  private static final ImmutableMap<String, Object> DEFAULTS;

  static {
    ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
    // TRANSITIVE_SOURCES is mandatory
    builder.put(USES_SHARED_LIBRARIES, false);
    builder.put(
        IMPORTS,
        Depset.of(SkylarkType.STRING, NestedSetBuilder.<String>emptySet(Order.COMPILE_ORDER)));
    builder.put(HAS_PY2_ONLY_SOURCES, false);
    builder.put(HAS_PY3_ONLY_SOURCES, false);
    DEFAULTS = builder.build();
  }

  private static Object getValue(StructImpl info, String fieldName) throws EvalException {
    Object fieldValue = info.getValue(fieldName);
    if (fieldValue == null) {
      fieldValue = DEFAULTS.get(fieldName);
      if (fieldValue == null) {
        throw new EvalException(
            /*location=*/ null, String.format("'py' provider missing '%s' field", fieldName));
      }
    }
    return fieldValue;
  }

  /**
   * Casts and returns the transitive sources field.
   *
   * @throws EvalException if the field does not exist or is not a depset of {@link Artifact}
   */
  public static NestedSet<Artifact> getTransitiveSources(StructImpl info) throws EvalException {
    Object fieldValue = getValue(info, TRANSITIVE_SOURCES);
    Depset castValue =
        SkylarkType.cast(
            fieldValue,
            Depset.class,
            Artifact.class,
            null,
            "'%s' provider's '%s' field should be a depset of Files (got a '%s')",
            PROVIDER_NAME,
            TRANSITIVE_SOURCES,
            EvalUtils.getDataTypeName(fieldValue, /*fullDetails=*/ true));
    try {
      NestedSet<Artifact> unwrappedValue = castValue.getSet(Artifact.class);
      if (!unwrappedValue.getOrder().isCompatible(Order.COMPILE_ORDER)) {
        throw new EvalException(
            /*location=*/ null,
            String.format(
                "Incompatible depset order for 'transitive_sources': expected 'default' or "
                    + "'postorder', but got '%s'",
                unwrappedValue.getOrder().getSkylarkName()));
      }
      return unwrappedValue;
    } catch (Depset.TypeException exception) {
      throw new EvalException(
          null,
          String.format(
              "expected field '%s' to be a depset of type 'file', but was a depset of type '%s'",
              TRANSITIVE_SOURCES, castValue.getContentType()),
          exception);
    }
  }

  /**
   * Casts and returns the uses-shared-libraries field (or its default value).
   *
   * @throws EvalException if the field exists and is not a boolean
   */
  public static boolean getUsesSharedLibraries(StructImpl info) throws EvalException {
    Object fieldValue = getValue(info, USES_SHARED_LIBRARIES);
    return SkylarkType.cast(
        fieldValue,
        Boolean.class,
        null,
        "'%s' provider's '%s' field should be a boolean (got a '%s')",
        PROVIDER_NAME,
        USES_SHARED_LIBRARIES,
        EvalUtils.getDataTypeName(fieldValue, /*fullDetails=*/ true));
  }

  /**
   * Casts and returns the imports field (or its default value).
   *
   * @throws EvalException if the field exists and is not a depset of strings
   */
  public static NestedSet<String> getImports(StructImpl info) throws EvalException {
    Object fieldValue = getValue(info, IMPORTS);
    Depset castValue =
        SkylarkType.cast(
            fieldValue,
            Depset.class,
            String.class,
            null,
            "'%s' provider's '%s' field should be a depset of strings (got a '%s')",
            PROVIDER_NAME,
            IMPORTS,
            EvalUtils.getDataTypeNameFromClass(fieldValue.getClass()));
    try {
      return castValue.getSet(String.class);
    } catch (Depset.TypeException exception) {
      throw new EvalException(
          null,
          String.format(
              "expected field '%s' to be a depset of type 'file', but was a depset of type '%s'",
              IMPORTS, castValue.getContentType()),
          exception);
    }
  }

  /**
   * Casts and returns the py2-only-sources field (or its default value).
   *
   * @throws EvalException if the field exists and is not a boolean
   */
  public static boolean getHasPy2OnlySources(StructImpl info) throws EvalException {
    Object fieldValue = getValue(info, HAS_PY2_ONLY_SOURCES);
    return SkylarkType.cast(
        fieldValue,
        Boolean.class,
        null,
        "'%s' provider's '%s' field should be a boolean (got a '%s')",
        PROVIDER_NAME,
        HAS_PY2_ONLY_SOURCES,
        EvalUtils.getDataTypeNameFromClass(fieldValue.getClass()));
  }

  /**
   * Casts and returns the py3-only-sources field (or its default value).
   *
   * @throws EvalException if the field exists and is not a boolean
   */
  public static boolean getHasPy3OnlySources(StructImpl info) throws EvalException {
    Object fieldValue = getValue(info, HAS_PY3_ONLY_SOURCES);
    return SkylarkType.cast(
        fieldValue,
        Boolean.class,
        null,
        "'%s' provider's '%s' field should be a boolean (got a '%s')",
        PROVIDER_NAME,
        HAS_PY3_ONLY_SOURCES,
        EvalUtils.getDataTypeNameFromClass(fieldValue.getClass()));
  }

  public static Builder builder() {
    return new Builder();
  }

  /** Builder for a legacy py provider struct. */
  public static class Builder {
    Depset transitiveSources = null;
    Boolean usesSharedLibraries = null;
    Depset imports = null;
    Boolean hasPy2OnlySources = null;
    Boolean hasPy3OnlySources = null;

    // Use the static builder() method instead.
    private Builder() {}

    public Builder setTransitiveSources(NestedSet<Artifact> transitiveSources) {
      this.transitiveSources = Depset.of(Artifact.TYPE, transitiveSources);
      return this;
    }

    public Builder setUsesSharedLibraries(boolean usesSharedLibraries) {
      this.usesSharedLibraries = usesSharedLibraries;
      return this;
    }

    public Builder setImports(NestedSet<String> imports) {
      this.imports = Depset.of(SkylarkType.STRING, imports);
      return this;
    }

    public Builder setHasPy2OnlySources(boolean hasPy2OnlySources) {
      this.hasPy2OnlySources = hasPy2OnlySources;
      return this;
    }

    public Builder setHasPy3OnlySources(boolean hasPy3OnlySources) {
      this.hasPy3OnlySources = hasPy3OnlySources;
      return this;
    }

    private static void put(
        ImmutableMap.Builder<String, Object> fields, String fieldName, Object value) {
      fields.put(fieldName, value != null ? value : DEFAULTS.get(fieldName));
    }

    public StructImpl build() {
      ImmutableMap.Builder<String, Object> fields = ImmutableMap.builder();
      Preconditions.checkNotNull(transitiveSources, "setTransitiveSources is required");
      put(fields, TRANSITIVE_SOURCES, transitiveSources);
      put(fields, USES_SHARED_LIBRARIES, usesSharedLibraries);
      put(fields, IMPORTS, imports);
      put(fields, HAS_PY2_ONLY_SOURCES, hasPy2OnlySources);
      put(fields, HAS_PY3_ONLY_SOURCES, hasPy3OnlySources);
      return StructProvider.STRUCT.create(fields.build(), "No such attribute '%s'");
    }
  }
}
