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

import com.google.common.base.Strings;
import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.platform.ConstraintCollection.DuplicateConstraintException;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.NativeInfo;
import com.google.devtools.build.lib.starlarkbuildapi.platform.PlatformInfoApi;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.util.StringUtilities;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Printer;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.syntax.Location;

/** Provider for a platform, which is a group of constraints and values. */
@Immutable
public class PlatformInfo extends NativeInfo
    implements PlatformInfoApi<ConstraintSettingInfo, ConstraintValueInfo> {

  /**
   * The literal key that will be used to copy the {@link #remoteExecutionProperties} from the
   * parent {@link PlatformInfo} into a new {@link PlatformInfo}'s {@link
   * #remoteExecutionProperties}.
   */
  public static final String PARENT_REMOTE_EXECUTION_KEY = "{PARENT_REMOTE_EXECUTION_PROPERTIES}";

  /** Name used in Starlark for accessing this provider. */
  public static final String STARLARK_NAME = "PlatformInfo";

  /** Provider singleton constant. */
  public static final BuiltinProvider<PlatformInfo> PROVIDER = new Provider();

  /** Provider for {@link ToolchainInfo} objects. */
  private static class Provider extends BuiltinProvider<PlatformInfo>
      implements PlatformInfoApi.Provider<
          ConstraintSettingInfo, ConstraintValueInfo, PlatformInfo> {
    private Provider() {
      super(STARLARK_NAME, PlatformInfo.class);
    }

    @Override
    public PlatformInfo platformInfo(
        Label label,
        Object parentUnchecked,
        Sequence<?> constraintValuesUnchecked,
        Object execPropertiesUnchecked,
        StarlarkThread thread)
        throws EvalException {
      PlatformInfo.Builder builder = PlatformInfo.builder();
      builder.setLabel(label);
      if (parentUnchecked != Starlark.NONE) {
        builder.setParent((PlatformInfo) parentUnchecked);
      }
      if (!constraintValuesUnchecked.isEmpty()) {
        builder.addConstraints(
            Sequence.cast(
                constraintValuesUnchecked, ConstraintValueInfo.class, "constraint_values"));
      }
      if (execPropertiesUnchecked != null) {
        Dict<String, String> execProperties =
            Dict.noneableCast(
                execPropertiesUnchecked, String.class, String.class, "exec_properties");
        builder.setExecProperties(ImmutableMap.copyOf(execProperties));
      }
      builder.setLocation(thread.getCallerLocation());

      try {
        return builder.build();
      } catch (DuplicateConstraintException | ExecPropertiesException e) {
        throw new EvalException(e);
      }
    }
  }

  private final Label label;
  private final ConstraintCollection constraints;
  private final String remoteExecutionProperties;
  /** execProperties will deprecate and replace remoteExecutionProperties */
  private final ImmutableMap<String, String> execProperties;

  private PlatformInfo(
      Label label,
      ConstraintCollection constraints,
      String remoteExecutionProperties,
      ImmutableMap<String, String> execProperties,
      Location creationLocation) {
    super(creationLocation);
    this.label = label;
    this.constraints = constraints;
    this.remoteExecutionProperties = Strings.nullToEmpty(remoteExecutionProperties);
    this.execProperties = execProperties;
  }

  /** Empty {@link PlatformInfo} instance representing an invalid or empty platform. */
  public static final PlatformInfo EMPTY_PLATFORM_INFO;

  static {
    try {
      EMPTY_PLATFORM_INFO = PlatformInfo.builder().build();
    } catch (DuplicateConstraintException | ExecPropertiesException e) {
      // This can never happen since we're not passing any values to the builder.
      throw new VerifyException(e);
    }
  }

  @Override
  public BuiltinProvider<PlatformInfo> getProvider() {
    return PROVIDER;
  }

  @Override
  public Label label() {
    return label;
  }

  @Override
  public ConstraintCollection constraints() {
    return constraints;
  }

  @Override
  public String remoteExecutionProperties() {
    return remoteExecutionProperties;
  }

  @Override
  public ImmutableMap<String, String> execProperties() {
    return execProperties;
  }

  @Override
  public void repr(Printer printer) {
    printer.append(String.format("PlatformInfo(%s, constraints=%s)", label, constraints));
  }

  /** Returns a new {@link Builder} for creating a fresh {@link PlatformInfo} instance. */
  public static Builder builder() {
    return new Builder();
  }

  /** Add this platform to the given fingerprint. */
  public void addTo(Fingerprint fp) {
    fp.addString(label.toString());
    fp.addNullableString(remoteExecutionProperties);
    fp.addStringMap(execProperties);
    constraints.addToFingerprint(fp);
  }

  /** Builder class to facilitate creating valid {@link PlatformInfo} instances. */
  public static class Builder {

    @Nullable private PlatformInfo parent = null;
    private Label label;
    private final ConstraintCollection.Builder constraints = ConstraintCollection.builder();
    private String remoteExecutionProperties = null;
    @Nullable private ImmutableMap<String, String> execProperties;
    private Location creationLocation = Location.BUILTIN;

    /**
     * Sets the parent {@link PlatformInfo} that this platform inherits from. Constraint values set
     * directly on this instance will be kept, but any other constraint settings will be found from
     * the parent, if set.
     *
     * @param parent the platform that is the parent of this platform
     * @return the {@link Builder} instance for method chaining
     */
    @CanIgnoreReturnValue
    public Builder setParent(@Nullable PlatformInfo parent) {
      this.parent = parent;
      if (parent == null) {
        this.constraints.parent(null);
      } else {
        this.constraints.parent(parent.constraints);
      }
      return this;
    }

    /**
     * Sets the {@link Label} for this {@link PlatformInfo}.
     *
     * @param label the label identifying this platform
     * @return the {@link Builder} instance for method chaining
     */
    @CanIgnoreReturnValue
    public Builder setLabel(Label label) {
      this.label = label;
      return this;
    }

    /**
     * Adds the given constraint value to the constraints that define this {@link PlatformInfo}.
     *
     * @param constraint the constraint to add
     * @return the {@link Builder} instance for method chaining
     */
    @CanIgnoreReturnValue
    public Builder addConstraint(ConstraintValueInfo constraint) {
      this.constraints.addConstraints(constraint);
      return this;
    }

    /**
     * Adds the given constraint values to the constraints that define this {@link PlatformInfo}.
     *
     * @param constraints the constraints to add
     * @return the {@link Builder} instance for method chaining
     */
    @CanIgnoreReturnValue
    public Builder addConstraints(Iterable<ConstraintValueInfo> constraints) {
      this.constraints.addConstraints(constraints);
      return this;
    }

    /**
     * Sets the data being sent to a potential remote executor. If there is a parent {@link
     * PlatformInfo} set, the literal string "{PARENT_REMOTE_EXECUTION_PROPERTIES}" will be replaced
     * by the {@link #remoteExecutionProperties} from that parent. Also if the parent is set, and
     * this instance's {@link #remoteExecutionProperties} is blank or unset, the parent's will be
     * used directly.
     *
     * <p>Specific examples:
     *
     * <ul>
     *   <li>parent.remoteExecutionProperties is unset: use the child's value
     *   <li>parent.remoteExecutionProperties is set, child.remoteExecutionProperties is unset: use
     *       the parent's value
     *   <li>parent.remoteExecutionProperties is set, child.remoteExecutionProperties is set, and
     *       does not contain {PARENT_REMOTE_EXECUTION_PROPERTIES}: use the child's value
     *   <li>parent.remoteExecutionProperties is set, child.remoteExecutionProperties is set, and
     *       does contain {PARENT_REMOTE_EXECUTION_PROPERTIES}: use the child's value, but
     *       substitute the parent's value for {PARENT_REMOTE_EXECUTION_PROPERTIES}
     * </ul>
     *
     * @param properties the properties to be added
     * @return the {@link Builder} instance for method chaining
     */
    @CanIgnoreReturnValue
    public Builder setRemoteExecutionProperties(String properties) {
      this.remoteExecutionProperties = properties;
      return this;
    }

    /**
     * Sets the execution properties.
     *
     * <p>If there is a parent {@link PlatformInfo} set, then all parent's properties will be
     * inherited. Any properties included in both will use the child's value. Use the value of empty
     * string to unset a property.
     */
    @CanIgnoreReturnValue
    public Builder setExecProperties(@Nullable ImmutableMap<String, String> properties) {
      this.execProperties = properties;
      return this;
    }

    /**
     * Sets the {@link Location} where this {@link PlatformInfo} was created.
     *
     * @param location the location where the instance was created
     * @return the {@link Builder} instance for method chaining
     */
    @CanIgnoreReturnValue
    public Builder setLocation(Location location) {
      this.creationLocation = location;
      return this;
    }

    private void checkRemoteExecutionProperties() throws ExecPropertiesException {
      if (execProperties != null && !Strings.isNullOrEmpty(remoteExecutionProperties)) {
        throw new ExecPropertiesException(
            "Platform contains both remote_execution_properties and exec_properties. Prefer"
                + " exec_properties over the deprecated remote_execution_properties.");
      }
      if (execProperties != null
          && parent != null
          && !Strings.isNullOrEmpty(parent.remoteExecutionProperties())) {
        throw new ExecPropertiesException(
            "Platform specifies exec_properties but its parent "
                + parent.label()
                + " specifies remote_execution_properties. Prefer exec_properties over the"
                + " deprecated remote_execution_properties.");
      }
      if (!Strings.isNullOrEmpty(remoteExecutionProperties)
          && parent != null
          && !parent.execProperties().isEmpty()) {
        throw new ExecPropertiesException(
            "Platform specifies remote_execution_properties but its parent specifies"
                + " exec_properties. Prefer exec_properties over the deprecated"
                + " remote_execution_properties.");
      }
    }

    /**
     * Returns the new {@link PlatformInfo} instance.
     *
     * @throws DuplicateConstraintException if more than one constraint value exists for the same
     *     constraint setting
     */
    public PlatformInfo build() throws DuplicateConstraintException, ExecPropertiesException {
      checkRemoteExecutionProperties();

      // Merge the remote execution properties.
      String remoteExecutionProperties =
          mergeRemoteExecutionProperties(parent, this.remoteExecutionProperties);

      ImmutableMap<String, String> execProperties =
          mergeExecProperties(parent, this.execProperties);
      if (execProperties == null) {
        execProperties = ImmutableMap.of();
      }

      return new PlatformInfo(
          label, constraints.build(), remoteExecutionProperties, execProperties, creationLocation);
    }

    private static String mergeRemoteExecutionProperties(
        PlatformInfo parent, String remoteExecutionProperties) {
      String parentRemoteExecutionProperties = "";
      if (parent != null) {
        parentRemoteExecutionProperties = parent.remoteExecutionProperties();
      }

      if (remoteExecutionProperties == null) {
        return parentRemoteExecutionProperties;
      }

      return StringUtilities.replaceAllLiteral(
          remoteExecutionProperties, PARENT_REMOTE_EXECUTION_KEY, parentRemoteExecutionProperties);
    }

    @Nullable
    private static ImmutableMap<String, String> mergeExecProperties(
        PlatformInfo parent, Map<String, String> execProperties) {
      if ((parent == null || parent.execProperties() == null) && execProperties == null) {
        return null;
      }

      HashMap<String, String> result = new HashMap<>();
      if (parent != null && parent.execProperties() != null) {
        result.putAll(parent.execProperties());
      }

      if (execProperties != null) {
        for (Map.Entry<String, String> entry : execProperties.entrySet()) {
          if (Strings.isNullOrEmpty(entry.getValue())) {
            result.remove(entry.getKey());
          } else {
            result.put(entry.getKey(), entry.getValue());
          }
        }
      }

      return ImmutableMap.copyOf(result);
    }
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof PlatformInfo)) {
      return false;
    }
    PlatformInfo that = (PlatformInfo) o;
    return Objects.equals(label, that.label)
        && Objects.equals(constraints, that.constraints)
        && Objects.equals(remoteExecutionProperties, that.remoteExecutionProperties)
        && Objects.equals(execProperties, that.execProperties);
  }

  @Override
  public int hashCode() {
    return Objects.hash(label, constraints, remoteExecutionProperties);
  }

  /** Exception that indicates something is wrong in exec_properties configuration. */
  public static class ExecPropertiesException extends Exception {
    ExecPropertiesException(String message) {
      super(message);
    }
  }
}
