// 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.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.syntax.Concatable;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.SkylarkClassObject;
import com.google.devtools.build.lib.syntax.SkylarkType;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * A standard implementation for provider instances.
 *
 * <p>Instances may be either schemaless or schemaful (corresponding to the two different concrete
 * implementing classes). Schemaless instances are map-based, while schemaful instances have a fixed
 * layout and array and are therefore more efficient.
 */
public abstract class SkylarkInfo extends Info implements Concatable, SkylarkClassObject {

  // Private because this should not be subclassed outside this file.
  private SkylarkInfo(Provider provider, @Nullable Location loc) {
    super(provider, loc);
  }

  @Override
  public Concatter getConcatter() {
    return SkylarkInfoConcatter.INSTANCE;
  }

  @Override
  public boolean isImmutable() {
    // If the provider is not yet exported, the hash code of the object is subject to change.
    if (!getProvider().isExported()) {
      return false;
    }
    // TODO(bazel-team): If we export at the end of a full module's evaluation, instead of at the
    // end of every top-level statement, then we can assume that exported implies frozen, and just
    // return true here without a traversal.
    for (Object item : getValues()) {
      if (item != null && !EvalUtils.isImmutable(item)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Returns all the field values stored in the object, in the canonical order.
   *
   * <p>{@code protected} because this is only used for {@link #isImmutable}. It saves us having to
   * get values one-by-one.
   */
  protected abstract Iterable<Object> getValues();

  /**
   * Returns the custom (i.e. per-instance, as opposed to per-provider-type) error message string
   * format used by this provider instance, or null if not set.
   */
  @Nullable
  public abstract String getCustomErrorMessageFormatForUnknownField();

  /** Returns the layout for this provider if it is schemaful, null otherwise. */
  @Nullable
  public abstract Layout getLayout();

  /** Returns true if this provider is schemaful (array-based), false otherwise. */
  public boolean isCompact() {
    return getLayout() != null;
  }

  /**
   * Creates a schemaless (map-based) provider instance with the given provider type and field
   * values.
   *
   * <p>{@code loc} is the creation location for this instance. Built-in provider instances may use
   * {@link Location#BUILTIN}, which is the default if null.
   */
  public static SkylarkInfo createSchemaless(
      Provider provider, Map<String, Object> values, @Nullable Location loc) {
    return new MapBackedSkylarkInfo(
        provider, values, loc, /*errorMessageFormatForUnknownField=*/ null);
  }

  /**
   * Creates a schemaless (map-based) provider instance with the given provider type, field values,
   * and unknown-field error message.
   *
   * <p>This is used to create structs for special purposes, such as {@code ctx.attr} and the
   * {@code native} module. The creation location will be {@link Location#BUILTIN}.
   *
   * <p>{@code errorMessageFormatForUnknownField} is a string format, as for {@link
   * Provider#getErrorMessageFormatForUnknownField}.
   *
   * <p>It is preferred to not use this method. Instead, create a new subclass of {@link
   * NativeProvider} with the desired error message format, and create a corresponding {@link
   * NativeInfo} subclass.
   */
  // TODO(bazel-team): Make the special structs that need a custom error message use a different
  // provider (subclassing NativeProvider) and a different Info implementation. Then remove this
  // functionality, thereby saving a string pointer field for the majority of providers that don't
  // need it.
  public static SkylarkInfo createSchemalessWithCustomMessage(
      Provider provider, Map<String, Object> values, String errorMessageFormatForUnknownField) {
    Preconditions.checkNotNull(errorMessageFormatForUnknownField);
    return new MapBackedSkylarkInfo(
        provider, values, Location.BUILTIN, errorMessageFormatForUnknownField);
  }

  /**
   * Creates a schemaful (array-based) provider instance with the given provider type, layout, and
   * values.
   *
   * <p>The order of the values must correspond to the given layout.
   *
   * <p>{@code loc} is the creation location for this instance. Built-in provider instances may use
   * {@link Location#BUILTIN}, which is the default if null.
   */
  public static SkylarkInfo createSchemaful(
      Provider provider,
      Layout layout,
      Object[] values,
      @Nullable Location loc) {
    return new CompactSkylarkInfo(provider, layout, values, loc);
  }

  /**
   * Returns the concrete implementation classes of this abstract class.
   *
   * <p>This is useful for code that depends on reflection.
   */
  public static List<Class<? extends SkylarkInfo>> getImplementationClasses() {
    return ImmutableList.of(MapBackedSkylarkInfo.class, CompactSkylarkInfo.class);
  }

  /**
   * A specification of what fields a provider instance has, and how they are ordered in an
   * array-backed implementation.
   *
   * <p>The provider instance may only have fields that appear in its layout. Not all fields in the
   * layout need be present on the instance.
   */
  @Immutable
  @AutoCodec
  public static final class Layout {

    /**
     * A map from field names to a contiguous range of integers [0, n), ordered by integer value.
     */
    private final ImmutableMap<String, Integer> map;

    /**
     * Constructs a {@link Layout} from the given field names.
     *
     * <p>The order of the field names is preserved in the layout.
     *
     * @throws IllegalArgumentException if any field names are given more than once
     */
    public Layout(Iterable<String> fields) {
      this(makeMap(fields));
    }

    @AutoCodec.VisibleForSerialization
    @AutoCodec.Instantiator
    Layout(ImmutableMap<String, Integer> map) {
      this.map = map;
    }

    private static ImmutableMap<String, Integer> makeMap(Iterable<String> fields) {
      ImmutableMap.Builder<String, Integer> layoutBuilder = ImmutableMap.builder();
      int i = 0;
      for (String field : fields) {
        layoutBuilder.put(field, i++);
      }
      return layoutBuilder.build();
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof Layout)) {
        return false;
      }
      if (map == other) {
        return true;
      }
      return map.equals(((Layout) other).map);
    }

    @Override
    public int hashCode() {
      return map.hashCode();
    }

    /** Returns the number of fields in the layout. */
    public int size() {
      return map.size();
    }

    /** Returns whether or not a field is mentioned in the layout. */
    public boolean hasField(String field) {
      return map.containsKey(field);
    }

    /**
     * Returns the index position associated with the given field, or null if the field is not
     * mentioned by the layout.
     */
    public Integer getFieldIndex(String field) {
      return map.get(field);
    }

    /** Returns the field names specified by this layout, in order. */
    public ImmutableCollection<String> getFields() {
      return map.keySet();
    }

    /** Returns the entry set of the underlying map, in order. */
    public ImmutableCollection<Map.Entry<String, Integer>> entrySet() {
      return map.entrySet();
    }
  }

  /** A {@link SkylarkInfo} implementation that stores its values in a map. */
  // TODO(b/72448383): Make private.
  public static final class MapBackedSkylarkInfo extends SkylarkInfo {

    private final ImmutableMap<String, Object> values;

    /**
     * Formattable string with one {@code '%s'} placeholder for the missing field name.
     *
     * <p>If null, uses the default format specified by the provider.
     */
    @Nullable
    private final String errorMessageFormatForUnknownField;

    MapBackedSkylarkInfo(
        Provider provider,
        Map<String, Object> values,
        @Nullable Location loc,
        @Nullable String errorMessageFormatForUnknownField) {
      super(provider, loc);
      // TODO(b/74396075): Phase out the unnecessary conversions done by this call to copyValues.
      this.values = copyValues(values);
      this.errorMessageFormatForUnknownField = errorMessageFormatForUnknownField;
    }

    @Override
    public boolean hasField(String name) {
      return values.containsKey(name);
    }

    @Override
    public Object getValue(String name) {
      return values.get(name);
    }

    @Override
    public ImmutableCollection<String> getFieldNames() {
      return values.keySet();
    }

    @Override
    protected Iterable<Object> getValues() {
      return values.values();
    }

    @Override
    protected String getErrorMessageFormatForUnknownField() {
      return errorMessageFormatForUnknownField != null
          ? errorMessageFormatForUnknownField : super.getErrorMessageFormatForUnknownField();
    }

    @Override
    public String getCustomErrorMessageFormatForUnknownField() {
      return errorMessageFormatForUnknownField;
    }

    @Override
    public Layout getLayout() {
      return null;
    }
  }

  /** A {@link SkylarkInfo} implementation that stores its values in array to save space. */
  private static final class CompactSkylarkInfo extends SkylarkInfo implements Concatable {

    private final Layout layout;
    /** Treated as immutable. */
    private final Object[] values;

    CompactSkylarkInfo(
        Provider provider,
        Layout layout,
        Object[] values,
        @Nullable Location loc) {
      super(provider, loc);
      this.layout = Preconditions.checkNotNull(layout);
      Preconditions.checkArgument(
          layout.size() == values.length,
          "Layout has length %s, but number of given values was %s", layout.size(), values.length);
      this.values = new Object[values.length];
      for (int i = 0; i < values.length; i++) {
        // TODO(b/74396075): Phase out this unnecessary conversion.
        this.values[i] = SkylarkType.convertToSkylark(values[i], (Environment) null);
      }
    }

    @Override
    public Object getValue(String name) {
      Integer index = layout.getFieldIndex(name);
      if (index == null) {
        return null;
      }
      return values[index];
    }

    @Override
    public boolean hasField(String name) {
      Integer index = layout.getFieldIndex(name);
      return index != null && values[index] != null;
    }

    @Override
    public ImmutableCollection<String> getFieldNames() {
      ImmutableSet.Builder<String> result = ImmutableSet.builder();
      for (Map.Entry<String, Integer> entry : layout.entrySet()) {
        if (values[entry.getValue()] != null) {
          result.add(entry.getKey());
        }
      }
      return result.build();
    }

    @Override
    protected Iterable<Object> getValues() {
      return Arrays.asList(values);
    }

    @Override
    public String getCustomErrorMessageFormatForUnknownField() {
      return null;
    }

    @Override
    public Layout getLayout() {
      return layout;
    }
  }

  /** Concatter for concrete {@link SkylarkInfo} subclasses. */
  private static final class SkylarkInfoConcatter implements Concatable.Concatter {
    private static final SkylarkInfoConcatter INSTANCE = new SkylarkInfoConcatter();

    private SkylarkInfoConcatter() {}

    @Override
    public Concatable concat(Concatable left, Concatable right, Location loc) throws EvalException {
      // Casts are safe because SkylarkInfoConcatter is only used by SkylarkInfo.
      SkylarkInfo leftInfo = (SkylarkInfo) left;
      SkylarkInfo rightInfo = (SkylarkInfo) right;
      Provider provider = leftInfo.getProvider();
      if (!provider.equals(rightInfo.getProvider())) {
        throw new EvalException(
            loc,
            String.format(
                "Cannot use '+' operator on instances of different providers (%s and %s)",
                provider.getPrintableName(), rightInfo.getProvider().getPrintableName()));
      }
      SetView<String> commonFields =
          Sets.intersection(
              ImmutableSet.copyOf(leftInfo.getFieldNames()),
              ImmutableSet.copyOf(rightInfo.getFieldNames()));
      if (!commonFields.isEmpty()) {
        throw new EvalException(
            loc,
            "Cannot use '+' operator on provider instances with overlapping field(s): "
                + Joiner.on(",").join(commonFields));
      }
      // Keep homogeneous compact concatenations compact.
      if (leftInfo instanceof CompactSkylarkInfo && rightInfo instanceof CompactSkylarkInfo) {
        CompactSkylarkInfo compactLeft = (CompactSkylarkInfo) leftInfo;
        CompactSkylarkInfo compactRight = (CompactSkylarkInfo) rightInfo;
        Layout layout = compactLeft.layout;
        if (layout.equals(compactRight.layout)) {
          int nvals = layout.size();
          Object[] newValues = new Object[nvals];
          for (int i = 0; i < nvals; i++) {
            newValues[i] =
                (compactLeft.values[i] != null) ? compactLeft.values[i] : compactRight.values[i];
          }
          return createSchemaful(provider, layout, newValues, loc);
        }
      }
      // Fall back on making a map-based instance.
      ImmutableMap.Builder<String, Object> newValues = ImmutableMap.builder();
      for (String field : leftInfo.getFieldNames()) {
        newValues.put(field, leftInfo.getValue(field));
      }
      for (String field : rightInfo.getFieldNames()) {
        newValues.put(field, rightInfo.getValue(field));
      }
      return createSchemaless(provider, newValues.build(), loc);
    }
  }
}
