// 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.analysis.platform;

import static com.google.common.collect.ImmutableListMultimap.flatteningToImmutableListMultimap;
import static com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static java.util.stream.Collectors.joining;

import com.google.auto.value.AutoValue;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.cmdline.Label;
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.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skylarkbuildapi.platform.ConstraintCollectionApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.syntax.Sequence;
import com.google.devtools.build.lib.util.Fingerprint;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import javax.annotation.Nullable;

/** A collection of constraint values. */
@Immutable
@AutoCodec
@AutoValue
public abstract class ConstraintCollection
    implements ConstraintCollectionApi<ConstraintSettingInfo, ConstraintValueInfo> {

  /** A builder class to help create instances of {@link ConstraintCollection}. */
  public static final class Builder {
    @Nullable private ConstraintCollection parent;
    private ImmutableList.Builder<ConstraintValueInfo> constraintValues =
        new ImmutableList.Builder<>();

    private Builder() {}

    /** Sets the parent {@link ConstraintCollection} of this instance. */
    public Builder parent(@Nullable ConstraintCollection parent) {
      this.parent = parent;
      return this;
    }

    /** Adds the given constraints to the current collection. */
    public Builder addConstraints(Map<ConstraintSettingInfo, ConstraintValueInfo> constraints) {
      return addConstraints(constraints.values());
    }

    /** Adds the given constraints to the current collection. */
    public Builder addConstraints(ConstraintValueInfo... constraints) {
      return addConstraints(ImmutableList.copyOf(constraints));
    }

    /** Adds the given constraints to the current collection. */
    public Builder addConstraints(Iterable<ConstraintValueInfo> constraints) {
      constraintValues.addAll(constraints);
      return this;
    }

    /** Returns the completed {@link ConstraintCollection} instance. */
    public ConstraintCollection build() throws DuplicateConstraintException {
      ImmutableList<ConstraintValueInfo> constraintValues = this.constraintValues.build();
      validateConstraints(constraintValues);
      return new AutoValue_ConstraintCollection(
          this.parent,
          constraintValues.stream()
              .collect(toImmutableMap(ConstraintValueInfo::constraint, Function.identity())));
    }
  }

  /** Returns a new {@link Builder} suitable for creating {@link ConstraintCollection} instances. */
  public static Builder builder() {
    return new Builder();
  }

  @AutoCodec.Instantiator
  @VisibleForSerialization
  static ConstraintCollection create(
      @Nullable ConstraintCollection parent,
      ImmutableMap<ConstraintSettingInfo, ConstraintValueInfo> constraints)
      throws DuplicateConstraintException {
    return builder().parent(parent).addConstraints(constraints).build();
  }

  /**
   * Returns the parent {@link ConstraintCollection} for this instance, or {@code null} if none
   * exists.
   */
  @Nullable
  abstract ConstraintCollection parent();

  /** Returns the constraints supplied by this collection. */
  abstract ImmutableMap<ConstraintSettingInfo, ConstraintValueInfo> constraints();

  /**
   * Returns {@code true} if this {@link ConstraintCollection} contains every {@link
   * ConstraintValueInfo} in {@code expected}, or if the expected constraint value is the default
   * for its setting.
   */
  public boolean containsAll(Iterable<ConstraintValueInfo> expected) {
    return findMissing(expected).isEmpty();
  }

  /**
   * Returns the set of {@link ConstraintValueInfo constraints} from {@code expected} that are not
   * present in this {@link ConstraintCollection}, either directly, or by being the default for
   * their {@link ConstraintSettingInfo}.
   */
  public ImmutableList<ConstraintValueInfo> findMissing(Iterable<ConstraintValueInfo> expected) {
    ImmutableList.Builder<ConstraintValueInfo> missing = new ImmutableList.Builder<>();
    // For every constraint check if it is (1) non-null and (2) set correctly.
    for (ConstraintValueInfo constraint : expected) {
      ConstraintSettingInfo setting = constraint.constraint();
      ConstraintValueInfo targetValue = get(setting);
      if (targetValue == null || !constraint.equals(targetValue)) {
        missing.add(constraint);
      }
    }
    return missing.build();
  }

  /**
   * Returns the set of {@link ConstraintSettingInfo settings} where this {@link
   * ConstraintCollection} and {@code other} have different {@link ConstraintValueInfo values}.
   */
  public ImmutableSet<ConstraintSettingInfo> diff(ConstraintCollection other) {
    ImmutableSet<ConstraintSettingInfo> constraintsToCheck =
        new ImmutableSet.Builder<ConstraintSettingInfo>()
            .addAll(this.constraintSettings())
            .addAll(other.constraintSettings())
            .build();
    ImmutableSet.Builder<ConstraintSettingInfo> mismatchSettings = new ImmutableSet.Builder<>();
    for (ConstraintSettingInfo constraintSetting : constraintsToCheck) {
      ConstraintValueInfo thisConstraint = this.get(constraintSetting);
      ConstraintValueInfo otherConstraint = other.get(constraintSetting);

      if (thisConstraint != null && !thisConstraint.equals(otherConstraint)) {
        mismatchSettings.add(constraintSetting);
      }
    }

    return mismatchSettings.build();
  }

  private ConstraintSettingInfo convertKey(Object key, Location loc) throws EvalException {
    if (!(key instanceof ConstraintSettingInfo)) {
      throw new EvalException(
          loc,
          String.format(
              "Constraint names must be platform_common.ConstraintSettingInfo, got %s instead",
              EvalUtils.getDataTypeName(key)));
    }

    return (ConstraintSettingInfo) key;
  }

  @Override
  public boolean has(ConstraintSettingInfo constraint) {
    // First, check locally.
    if (constraints().containsKey(constraint)) {
      return true;
    }

    // Then, check the parent.
    if (parent() != null) {
      return parent().has(constraint);
    }

    return constraint.hasDefaultConstraintValue();
  }

  public boolean hasWithoutDefault(ConstraintSettingInfo constraint) {
    // First, check locally.
    if (constraints().containsKey(constraint)) {
      return true;
    }

    // Then, check the parent, directly to ignore defaults.
    if (parent() != null) {
      return parent().hasWithoutDefault(constraint);
    }

    return false;
  }

  /**
   * Returns the {@link ConstraintValueInfo} for the given {@link ConstraintSettingInfo}, or {@code
   * null} if none exists.
   */
  @Nullable
  @Override
  public ConstraintValueInfo get(ConstraintSettingInfo constraint) {
    // First, check locally.
    if (constraints().containsKey(constraint)) {
      return constraints().get(constraint);
    }

    // Then, check the parent, directly to ignore defaults.
    if (parent() != null) {
      return parent().get(constraint);
    }

    // Finally, Since this constraint isn't set, fall back to the default.
    return constraint.defaultConstraintValue();
  }

  @Override
  public Sequence<ConstraintSettingInfo> constraintSettings() {
    return Sequence.createImmutable(constraints().keySet());
  }

  @Override
  public Object getIndex(Object key, Location loc) throws EvalException {
    ConstraintSettingInfo constraint = convertKey(key, loc);
    return get(constraint);
  }

  @Override
  public boolean containsKey(Object key, Location loc) throws EvalException {
    ConstraintSettingInfo constraint = convertKey(key, loc);
    return has(constraint);
  }

  // It's easier to use the Starlark repr as a string form, not what AutoValue produces.
  @Override
  public final String toString() {
    return Printer.str(this);
  }

  @Override
  public void repr(SkylarkPrinter printer) {
    printer.append("<");
    if (parent() != null) {
      printer.append("parent: ");
      parent().repr(printer);
      printer.append(", ");
    }
    printer.append("[");
    printer.append(
        constraints().values().stream()
            .map(ConstraintValueInfo::label)
            .map(Functions.toStringFunction())
            .collect(joining(", ")));
    printer.append("]");
    printer.append(">");
  }

  /**
   * Adds information to the {@link Fingerprint} to uniquely identify this collection of
   * constraints.
   */
  public void addToFingerprint(Fingerprint fp) {
    // Encode whether there is a parent.
    fp.addBoolean(parent() != null);
    // Add the parent.
    if (parent() != null) {
      parent().addToFingerprint(fp);
    }
    // Add the actual constraints.
    fp.addInt(constraints().size());
    constraints().values().forEach(constraintValue -> constraintValue.addTo(fp));
  }

  public static void validateConstraints(Iterable<ConstraintValueInfo> constraintValues)
      throws DuplicateConstraintException {
    // Collect the constraints by the settings.
    ImmutableListMultimap<ConstraintSettingInfo, ConstraintValueInfo> constraints =
        Streams.stream(constraintValues)
            .collect(
                toImmutableListMultimap(ConstraintValueInfo::constraint, Functions.identity()));

    // Find settings with duplicate values.
    ImmutableListMultimap<ConstraintSettingInfo, ConstraintValueInfo> duplicates =
        constraints.asMap().entrySet().stream()
            .filter(e -> e.getValue().size() > 1)
            .collect(
                flatteningToImmutableListMultimap(Map.Entry::getKey, e -> e.getValue().stream()));

    if (!duplicates.isEmpty()) {
      throw new DuplicateConstraintException(duplicates);
    }
  }

  /**
   * Exception class used when more than one {@link ConstraintValueInfo} for the same {@link
   * ConstraintSettingInfo} is added to a {@link Builder}.
   */
  public static class DuplicateConstraintException extends Exception {
    private final ImmutableListMultimap<ConstraintSettingInfo, ConstraintValueInfo>
        duplicateConstraints;

    DuplicateConstraintException(
        ListMultimap<ConstraintSettingInfo, ConstraintValueInfo> duplicateConstraints) {
      super(formatError(duplicateConstraints));
      this.duplicateConstraints = ImmutableListMultimap.copyOf(duplicateConstraints);
    }

    public ImmutableListMultimap<ConstraintSettingInfo, ConstraintValueInfo>
        duplicateConstraints() {
      return duplicateConstraints;
    }

    public static String formatError(
        ListMultimap<ConstraintSettingInfo, ConstraintValueInfo> duplicateConstraints) {
      return String.format(
          "Duplicate constraint values detected: %s",
          duplicateConstraints.asMap().entrySet().stream()
              .map(DuplicateConstraintException::describeSingleDuplicateConstraintSetting)
              .collect(joining(", ")));
    }

    private static String describeSingleDuplicateConstraintSetting(
        Map.Entry<ConstraintSettingInfo, Collection<ConstraintValueInfo>> duplicate) {
      return String.format(
          "constraint_setting %s has [%s]",
          duplicate.getKey().label(),
          duplicate.getValue().stream()
              .map(ConstraintValueInfo::label)
              .map(Label::toString)
              .collect(joining(", ")));
    }
  }
}
