// 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.ImmutableList;
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.Objects;
import javax.annotation.Nullable;
import net.starlark.java.eval.Printer;
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";

  /** 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);
    }
  }

  /** Provider singleton constant. */
  public static final BuiltinProvider<PlatformInfo> PROVIDER =
      new BuiltinProvider<PlatformInfo>(STARLARK_NAME, PlatformInfo.class) {};

  private final Label label;
  private final ConstraintCollection constraints;
  private final String remoteExecutionProperties;

  /** execProperties will deprecate and replace remoteExecutionProperties */
  // TODO(blaze-configurability): If we want to remove remoteExecutionProperties, we need to fix
  // PlatformUtils.getPlatformProto to use the dict-typed execProperties and do a migration.
  private final PlatformProperties execProperties;

  private final ImmutableList<String> flags;

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

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

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

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

  public String remoteExecutionProperties() {
    return remoteExecutionProperties;
  }

  public ImmutableMap<String, String> execProperties() {
    return execProperties.properties();
  }

  public ImmutableList<String> flags() {
    return flags;
  }

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

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

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof PlatformInfo that)) {
      return false;
    }
    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, execProperties);
  }

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

  /** 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;
    private final PlatformProperties.Builder execPropertiesBuilder = PlatformProperties.builder();
    private final ImmutableList.Builder<String> flags = new ImmutableList.Builder<>();
    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);
        this.execPropertiesBuilder.setParent(null);
      } else {
        this.constraints.parent(parent.constraints);
        this.execPropertiesBuilder.setParent(parent.execProperties);
      }
      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.execPropertiesBuilder.setProperties(properties);
      return this;
    }

    /** Add the given flags to this {@link PlatformInfo}. */
    @CanIgnoreReturnValue
    public Builder addFlags(Iterable<String> flags) {
      this.flags.addAll(flags);
      return this;
    }

    private static void checkRemoteExecutionProperties(
        PlatformInfo parent,
        String remoteExecutionProperties,
        ImmutableMap<String, String> execProperties)
        throws ExecPropertiesException {
      if (!execProperties.isEmpty() && !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.isEmpty()
          && 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(
          this.parent, this.remoteExecutionProperties, execPropertiesBuilder.getProperties());

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

      // Merge parent flags and this builder's flags. Parent flags always come first so that flags
      // from this builder will override or combine, depending on the flag type.
      ImmutableList.Builder<String> flagBuilder = new ImmutableList.Builder<>();
      if (this.parent != null) {
        flagBuilder.addAll(this.parent.flags);
      }
      flagBuilder.addAll(this.flags.build());

      return new PlatformInfo(
          label,
          constraints.build(),
          remoteExecutionProperties,
          execPropertiesBuilder.build(),
          flagBuilder.build(),
          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);
    }
  }

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