// 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.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.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.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkList;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.util.Fingerprint;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
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 static ConstraintSettingInfo convertKey(Object key) throws EvalException {
    if (!(key instanceof ConstraintSettingInfo)) {
      throw Starlark.errorf(
          "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;
  }

  @Override
  public boolean hasConstraintValue(ConstraintValueInfo constraintValue) {
    ConstraintValueInfo discoveredConstraintValue = this.get(constraintValue.constraint());
    return Objects.equals(constraintValue, discoveredConstraintValue);
  }

  /**
   * 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 StarlarkList.immutableCopyOf(constraints().keySet());
  }

  @Override
  public Object getIndex(StarlarkSemantics semantics, Object key) throws EvalException {
    return get(convertKey(key));
  }

  @Override
  public boolean containsKey(StarlarkSemantics semantics, Object key) throws EvalException {
    return has(convertKey(key));
  }

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

  @Override
  public void repr(Printer 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(", ")));
    }
  }
}
