// Copyright 2021 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;

import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.devtools.build.lib.packages.ExecGroup.DEFAULT_EXEC_GROUP_NAME;
import static java.util.stream.Collectors.joining;

import com.google.auto.value.AutoValue;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.ExecGroup;
import com.google.devtools.build.lib.server.FailureDetails.Analysis;
import com.google.devtools.build.lib.server.FailureDetails.Analysis.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.SaneAnalysisException;
import com.google.devtools.build.lib.util.DetailedExitCode;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * A container class for groups of {@link ExecGroup} instances. This correctly handles exec group
 * inheritance between rules and targets. See https://bazel.build/reference/exec-groups for further
 * details.
 */
@AutoValue
public abstract class ExecGroupCollection {
  /**
   * Prepares the input exec groups to serve as {@link Builder#execGroups}.
   *
   * <p>Applies any inheritance specified via {@link ExecGroup#copyFrom} and adds auto exec groups
   * when {@code useAutoExecGroups} is true.
   */
  public static ImmutableMap<String, ExecGroup> process(
      ImmutableMap<String, ExecGroup> execGroups,
      ImmutableSet<Label> defaultExecWith,
      ImmutableSet<ToolchainTypeRequirement> defaultToolchainTypes,
      boolean useAutoExecGroups) {
    var processedGroups =
        Maps.<String, ExecGroup>newHashMapWithExpectedSize(
            useAutoExecGroups
                ? (execGroups.size() + defaultToolchainTypes.size())
                : execGroups.size());
    for (Map.Entry<String, ExecGroup> entry : execGroups.entrySet()) {
      String name = entry.getKey();
      ExecGroup execGroup = entry.getValue();

      if (execGroup.copyFrom() != null) {
        if (execGroup.copyFrom().equals(DEFAULT_EXEC_GROUP_NAME)) {
          execGroup =
              ExecGroup.builder()
                  .execCompatibleWith(defaultExecWith)
                  .toolchainTypes(defaultToolchainTypes)
                  .build();
        } else {
          execGroup = execGroup.inheritFrom(execGroups.get(execGroup.copyFrom()));
        }
      }

      processedGroups.put(name, execGroup);
    }

    if (useAutoExecGroups) {
      // Creates one exec group for each toolchain (automatic exec groups).
      for (ToolchainTypeRequirement toolchainType : defaultToolchainTypes) {
        processedGroups.put(
            toolchainType.toolchainType().toString(),
            ExecGroup.builder()
                .addToolchainType(toolchainType)
                .copyFrom(null)
                .execCompatibleWith(defaultExecWith)
                .build());
      }
    }
    return ImmutableMap.copyOf(processedGroups);
  }

  /** Builder class for correctly constructing ExecGroupCollection instances. */
  // Note that this is _not_ an actual @AutoValue.Builder: it provides more logic and has different
  // fields.
  public abstract static class Builder {
    public abstract ImmutableMap<String, ExecGroup> execGroups();

    public ExecGroupCollection build(
        @Nullable ToolchainCollection<ResolvedToolchainContext> toolchainContexts,
        ImmutableMap<String, String> rawExecProperties)
        throws InvalidExecGroupException {

      // For each exec group, compute the combined execution properties.
      ImmutableTable<String, String, String> combinedExecProperties =
          computeCombinedExecProperties(toolchainContexts, rawExecProperties);

      return new AutoValue_ExecGroupCollection(execGroups(), combinedExecProperties);
    }
  }

  /**
   * Gets the combined exec properties of the platform and the target's exec properties. If a
   * property is set in both, the target properties take precedence.
   */
  private static ImmutableTable<String, String, String> computeCombinedExecProperties(
      @Nullable ToolchainCollection<ResolvedToolchainContext> toolchainContexts,
      ImmutableMap<String, String> rawExecProperties)
      throws InvalidExecGroupException {

    ImmutableSet<String> execGroupNames;
    if (toolchainContexts == null) {
      execGroupNames = ImmutableSet.of(DEFAULT_EXEC_GROUP_NAME);
    } else {
      execGroupNames = toolchainContexts.getExecGroupNames();
    }

    // Parse the target-level exec properties.
    ImmutableTable<String, String, String> parsedTargetProperties =
        parseExecProperties(rawExecProperties);
    // Validate the exec group names in the properties.
    if (toolchainContexts != null) {
      ImmutableSet<String> unknownTargetExecGroupNames =
          parsedTargetProperties.rowKeySet().stream()
              .filter(name -> !name.equals(DEFAULT_EXEC_GROUP_NAME))
              .filter(name -> !execGroupNames.contains(name))
              .collect(toImmutableSet());
      if (!unknownTargetExecGroupNames.isEmpty()) {
        throw new InvalidExecGroupException(unknownTargetExecGroupNames);
      }
    }

    // Parse each execution platform's exec properties.
    ImmutableSet<PlatformInfo> executionPlatforms;
    if (toolchainContexts == null) {
      executionPlatforms = ImmutableSet.of();
    } else {
      executionPlatforms =
          execGroupNames.stream()
              .map(name -> toolchainContexts.getToolchainContext(name).executionPlatform())
              .distinct()
              .collect(toImmutableSet());
    }
    Map<PlatformInfo, ImmutableTable<String, String, String>> parsedPlatformProperties =
        new LinkedHashMap<>();
    for (PlatformInfo executionPlatform : executionPlatforms) {
      ImmutableTable<String, String, String> parsed =
          parseExecProperties(executionPlatform.execProperties());
      parsedPlatformProperties.put(executionPlatform, parsed);
    }

    // First, get the defaults.
    ImmutableMap<String, String> defaultExecProperties =
        parsedTargetProperties.row(DEFAULT_EXEC_GROUP_NAME);
    Table<String, String, String> result = HashBasedTable.create();
    putAll(result, DEFAULT_EXEC_GROUP_NAME, defaultExecProperties);

    for (String execGroupName : execGroupNames) {
      ImmutableMap<String, String> combined =
          computeProperties(
              execGroupName,
              defaultExecProperties,
              toolchainContexts,
              parsedPlatformProperties,
              parsedTargetProperties);
      putAll(result, execGroupName, combined);
    }

    return ImmutableTable.copyOf(result);
  }

  private static <R, C, V> void putAll(Table<R, C, V> builder, R row, Map<C, V> values) {
    for (Map.Entry<C, V> entry : values.entrySet()) {
      builder.put(row, entry.getKey(), entry.getValue());
    }
  }

  private static ImmutableMap<String, String> computeProperties(
      String execGroupName,
      ImmutableMap<String, String> defaultExecProperties,
      @Nullable ToolchainCollection<ResolvedToolchainContext> toolchainContexts,
      Map<PlatformInfo, ImmutableTable<String, String, String>> parsedPlatformProperties,
      ImmutableTable<String, String, String> parsedTargetProperties) {

    ImmutableMap<String, String> defaultExecGroupPlatformProperties;
    ImmutableMap<String, String> platformProperties;
    if (toolchainContexts == null) {
      defaultExecGroupPlatformProperties = ImmutableMap.of();
      platformProperties = ImmutableMap.of();
    } else {
      PlatformInfo executionPlatform =
          toolchainContexts.getToolchainContext(execGroupName).executionPlatform();
      defaultExecGroupPlatformProperties =
          parsedPlatformProperties.get(executionPlatform).row(DEFAULT_EXEC_GROUP_NAME);
      platformProperties = parsedPlatformProperties.get(executionPlatform).row(execGroupName);
    }
    Map<String, String> targetProperties =
        new LinkedHashMap<>(parsedTargetProperties.row(execGroupName));
    for (String propertyName : defaultExecProperties.keySet()) {
      // If the property exists in the default and not in the target, copy it.
      targetProperties.computeIfAbsent(propertyName, defaultExecProperties::get);
    }

    // Combine the target and exec platform properties. Target properties take precedence.
    // Use a HashMap instead of an ImmutableMap.Builder because we expect duplicate keys.
    Map<String, String> combined = new LinkedHashMap<>();
    combined.putAll(defaultExecGroupPlatformProperties);
    combined.putAll(defaultExecProperties);
    combined.putAll(platformProperties);
    combined.putAll(targetProperties);
    return ImmutableMap.copyOf(combined);
  }

  protected abstract ImmutableMap<String, ExecGroup> execGroups();

  protected abstract ImmutableTable<String, String, String> execProperties();

  public ExecGroup getExecGroup(String execGroupName) {
    return execGroups().get(execGroupName);
  }

  public ImmutableMap<String, String> getExecProperties(String execGroupName) {
    return execProperties().row(execGroupName);
  }

  /**
   * Parse raw exec properties attribute value into a map of exec group names to their properties.
   * The raw map can have keys of two forms: (1) 'property' and (2) 'exec_group_name.property'. The
   * former get parsed into the default exec group, the latter get parsed into their relevant exec
   * groups.
   */
  private static ImmutableTable<String, String, String> parseExecProperties(
      Map<String, String> rawExecProperties) {
    ImmutableTable.Builder<String, String, String> execProperties = ImmutableTable.builder();
    for (Map.Entry<String, String> execProperty : rawExecProperties.entrySet()) {
      String rawProperty = execProperty.getKey();
      int delimiterIndex = rawProperty.indexOf('.');
      if (delimiterIndex == -1) {
        execProperties.put(DEFAULT_EXEC_GROUP_NAME, rawProperty, execProperty.getValue());
      } else {
        String execGroup = rawProperty.substring(0, delimiterIndex);
        String property = rawProperty.substring(delimiterIndex + 1);
        execProperties.put(execGroup, property, execProperty.getValue());
      }
    }
    return execProperties.buildOrThrow();
  }

  /** An error for when the user tries to access a non-existent exec group. */
  public static final class InvalidExecGroupException extends Exception
      implements SaneAnalysisException {

    public InvalidExecGroupException(Collection<String> invalidNames) {
      super(
          String.format(
              "Tried to set properties for non-existent exec groups: %s.",
              invalidNames.stream().collect(joining(","))));
    }

    @Override
    public DetailedExitCode getDetailedExitCode() {
      return DetailedExitCode.of(
          FailureDetail.newBuilder()
              .setMessage(getMessage())
              .setAnalysis(Analysis.newBuilder().setCode(Code.EXEC_GROUP_MISSING))
              .build());
    }
  }
}
