// 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.ImmutableSortedMap;
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 StructImpl 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 StructImpl 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 ImmutableSortedMap<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);
    }
  }
}
