// Copyright 2014 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.extra;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.CommandLine;
import com.google.devtools.build.lib.actions.RunfilesSupplier;
import com.google.devtools.build.lib.analysis.BashCommandConstructor;
import com.google.devtools.build.lib.analysis.CommandHelper;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

/**
 * The specification for a particular extra action type.
 */
@Immutable
public final class ExtraActionSpec implements TransitiveInfoProvider {
  private final PathFragment shExecutable;
  private final NestedSet<Artifact> resolvedTools;
  private final RunfilesSupplier runfilesSupplier;
  private final ImmutableList<Artifact> resolvedData;
  private final ImmutableList<String> outputTemplates;
  private final ImmutableMap<String, String> executionInfo;
  private final String command;
  private final boolean requiresActionOutput;
  private final Label label;

  public ExtraActionSpec(
      PathFragment shExecutable,
      NestedSet<Artifact> resolvedTools,
      RunfilesSupplier runfilesSupplier,
      List<Artifact> resolvedData,
      List<String> outputTemplates,
      String command,
      Label label,
      Map<String, String> executionInfo,
      boolean requiresActionOutput) {
    this.shExecutable = shExecutable;
    this.resolvedTools = resolvedTools;
    this.runfilesSupplier = runfilesSupplier;
    this.resolvedData = ImmutableList.copyOf(resolvedData);
    this.outputTemplates = ImmutableList.copyOf(outputTemplates);
    this.command = command;
    this.label = label;
    this.executionInfo = ImmutableMap.copyOf(executionInfo);
    this.requiresActionOutput = requiresActionOutput;
  }

  public Label getLabel() {
    return label;
  }

  /** Adds an extra_action to the action graph based on the action to shadow. */
  public Collection<Artifact.DerivedArtifact> addExtraAction(
      RuleContext owningRule, Action actionToShadow) {
    Collection<Artifact.DerivedArtifact> extraActionOutputs = new LinkedHashSet<>();
    Collection<Artifact.DerivedArtifact> protoOutputs = new ArrayList<>();
    NestedSetBuilder<Artifact> extraActionInputs = NestedSetBuilder.stableOrder();

    Label ownerLabel = owningRule.getLabel();
    if (requiresActionOutput || actionToShadow.discoversInputs()) {
      extraActionInputs.addAll(actionToShadow.getOutputs());
    }

    extraActionInputs.addTransitive(resolvedTools);
    extraActionInputs.addAll(resolvedData);

    boolean createDummyOutput = false;

    for (String outputTemplate : outputTemplates) {
      // We create output for the extra_action based on the 'out_template' attribute.
      // See {link #getExtraActionOutputArtifact} for supported variables.
      extraActionOutputs.add(getExtraActionOutputArtifact(
          owningRule, actionToShadow, outputTemplate));
    }
    // extra_action has no output, we need to create some dummy output to keep the build up-to-date.
    if (extraActionOutputs.isEmpty()) {
      createDummyOutput = true;
      extraActionOutputs.add(getExtraActionOutputArtifact(
          owningRule, actionToShadow, "$(ACTION_ID).dummy"));
    }

    // We generate a file containing a protocol buffer describing the action that is being shadowed.
    // It is up to each action being shadowed to decide what contents to store here.
    Artifact.DerivedArtifact extraActionInfoFile =
        getExtraActionOutputArtifact(owningRule, actionToShadow, "$(ACTION_ID).xa");
    owningRule.registerAction(new ExtraActionInfoFileWriteAction(
        actionToShadow.getOwner(), extraActionInfoFile, actionToShadow));
    extraActionInputs.add(extraActionInfoFile);
    protoOutputs.add(extraActionInfoFile);

    // Expand extra_action specific variables from the provided command-line.
    // See {@link #createExpandedCommand} for list of supported variables.
    String command = createExpandedCommand(owningRule, actionToShadow, extraActionInfoFile);

    CommandHelper commandHelper = CommandHelper.builder(owningRule).build();

    // Multiple actions in the same configured target need to have different names for the artifact
    // that might be created here, so we append something that should be unique for each action.
    String actionUniquifier =
        actionToShadow.getPrimaryOutput().getExecPath().getBaseName()
            + "."
            + actionToShadow.getKey(owningRule.getActionKeyContext());
    BashCommandConstructor constructor =
        CommandHelper.buildBashCommandConstructor(
            executionInfo, shExecutable, "." + actionUniquifier + ".extra_action_script.sh");
    List<String> argv = commandHelper.buildCommandLine(command, extraActionInputs, constructor);

    String commandMessage = String.format("Executing extra_action %s on %s", label, ownerLabel);
    owningRule.registerAction(
        new ExtraAction(
            extraActionInputs.build(),
            runfilesSupplier,
            extraActionOutputs,
            actionToShadow,
            createDummyOutput,
            CommandLine.of(argv),
            owningRule.getConfiguration().getActionEnvironment(),
            owningRule.getConfiguration().modifiedExecutionInfo(executionInfo, label.getName()),
            commandMessage,
            label.getName()));

    return ImmutableSet.<Artifact.DerivedArtifact>builder()
        .addAll(extraActionOutputs)
        .addAll(protoOutputs)
        .build();
  }

  /**
   * Expand extra_action specific variables:
   * $(EXTRA_ACTION_FILE): expands to a path of the file containing a protocol buffer
   * describing the action being shadowed.
   * $(output <out_template>): expands the output template to the execPath of the file.
   * e.g. $(output $(ACTION_ID).out) ->
   * <build_path>/extra_actions/bar/baz/devtools/build/test_A41234.out
   */
  private String createExpandedCommand(RuleContext owningRule,
      Action action, Artifact extraActionInfoFile) {
    String realCommand = command.replace(
        "$(EXTRA_ACTION_FILE)", extraActionInfoFile.getExecPathString());

    for (String outputTemplate : outputTemplates) {
      String outFile = getExtraActionOutputArtifact(owningRule, action, outputTemplate)
        .getExecPathString();
      realCommand = realCommand.replace("$(output " + outputTemplate + ")", outFile);
    }
    return realCommand;
  }

  /**
   * Creates an output artifact for the extra_action based on the output_template. The path will be
   * in the following form: <output
   * dir>/<target-configuration-specific-path>/extra_actions/<extra_action_label>/ +
   * <configured_target_label>/<expanded_template>
   *
   * <p>The template can use the following variables: $(ACTION_ID): a unique id for the
   * extra_action.
   *
   * <p>Sample: extra_action: foo/bar:extra template: $(ACTION_ID).analysis target: foo/bar:main
   * expands to: output/configuration/extra_actions/\
   * foo/bar/extra/foo/bar/4683026f7ac1dd1a873ccc8c3d764132.analysis
   */
  private Artifact.DerivedArtifact getExtraActionOutputArtifact(
      RuleContext ruleContext, Action action, String template) {
    String actionId =
        getActionId(ruleContext.getActionKeyContext(), ruleContext.getActionOwner(), action);

    template = template.replace("$(ACTION_ID)", actionId);
    template = template.replace("$(OWNER_LABEL_DIGEST)", getOwnerDigest(ruleContext));

    return getRootRelativePath(template, ruleContext);
  }

  private Artifact.DerivedArtifact getRootRelativePath(String template, RuleContext ruleContext) {
    PathFragment extraActionPackageFragment = label.getPackageIdentifier().getSourceRoot();
    PathFragment extraActionPrefix = extraActionPackageFragment.getRelative(label.getName());
    PathFragment rootRelativePath = PathFragment.create("extra_actions")
        .getRelative(extraActionPrefix)
        .getRelative(ruleContext.getPackageDirectory())
        .getRelative(template);
    // We need to use getDerivedArtifact here because extra actions are at
    // <EXTRA ACTION LABEL> / <RULE LABEL> instead of <RULE LABEL> / <EXTRA ACTION LABEL>. Bummer.
    return ruleContext.getAnalysisEnvironment().getDerivedArtifact(rootRelativePath,
        ruleContext.getConfiguration().getOutputDirectory(ruleContext.getRule().getRepository()));
  }

  /**
   * Calculates a digest representing the rule context.  We use the digest instead of the
   * original value as the original value might lead to a filename that is too long.
   * By using a digest, tools can deterministically find all extra_action outputs for a given
   * target, without having to open every file in the package.
   */
  private static String getOwnerDigest(RuleContext ruleContext) {
    Fingerprint f = new Fingerprint();
    f.addString(ruleContext.getLabel().toString());
    return f.hexDigestAndReset();
  }

  /**
   * Creates a unique id for the action shadowed by this extra_action.
   *
   * <p>We need to have a unique id for the extra_action to use. We build this from the owner's
   * label and the shadowed action id (which is only guaranteed to be unique per target). Together
   * with the subfolder matching the original target's package name, we believe this is enough of a
   * uniqueness guarantee.
   */
  @VisibleForTesting
  public static String getActionId(
      ActionKeyContext actionKeyContext, ActionOwner owner, Action action) {
    Fingerprint f = new Fingerprint();
    f.addString(owner.getLabel().toString());
    ImmutableList<AspectDescriptor> aspectDescriptors = owner.getAspectDescriptors();
    f.addInt(aspectDescriptors.size());
    for (AspectDescriptor aspectDescriptor : aspectDescriptors) {
      f.addString(aspectDescriptor.getDescription());
    }
    f.addString(action.getKey(actionKeyContext));
    return f.hexDigestAndReset();
  }
}
