// 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.runtime.commands;

import com.google.common.base.Predicate;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
import com.google.devtools.build.lib.actions.ActionGraph;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
import com.google.devtools.build.lib.actions.extra.DetailedExtraActionInfo;
import com.google.devtools.build.lib.actions.extra.ExtraActionSummary;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.PrintActionVisitor;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.buildtool.BuildRequest;
import com.google.devtools.build.lib.buildtool.BuildResult;
import com.google.devtools.build.lib.buildtool.BuildTool;
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.collect.nestedset.Order;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.LoadingOptions;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.KeepGoingOption;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingResult;
import com.google.protobuf.TextFormat;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * Implements 'blaze print_action' by finding the Configured target[s] for the file[s] listed.
 *
 */
@Command(name = "print_action",
         builds = true,
         inherits = {BuildCommand.class},
         options = {PrintActionCommand.PrintActionOptions.class},
         help = "resource:print_action.txt",
         shortDescription = "Prints the command line args for compiling a file.",
         completion = "label",
         allowResidue = true,
         canRunInOutputDirectory = true)
public final class PrintActionCommand implements BlazeCommand {

  @Override
  public void editOptions(OptionsParser optionsParser) { }

  /**
   * Options for print_action, used to parse command-line arguments.
   */
  public static class PrintActionOptions extends OptionsBase {
    @Option(
      name = "print_action_mnemonics",
      allowMultiple = true,
      defaultValue = "",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help =
          "Lists which mnemonics to filter print_action data by, no filtering takes place "
              + "when left empty."
    )
    public List<String> printActionMnemonics = new ArrayList<>();
  }

  @Override
  public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult options) {
    LoadingOptions loadingOptions =
        options.getOptions(LoadingOptions.class);

    PrintActionOptions printActionOptions = options.getOptions(PrintActionOptions.class);
    PrintActionRunner runner = new PrintActionRunner(loadingOptions.compileOneDependency, options,
        env.getReporter().getOutErr(),
        options.getResidue(), Sets.newHashSet(printActionOptions.printActionMnemonics));
    return BlazeCommandResult.exitCode(runner.printActionsForTargets(env));
  }

  /**
   * Contains all the logic to get extra_action information for print actions.
   * Maintains requires state to perform required analyses.
   */
  private class PrintActionRunner {
    private final boolean compileOneDependency;
    private final OptionsParsingResult options;
    private final OutErr outErr;
    private final List<String> requestedTargets;
    private final boolean keepGoing;
    private final ExtraActionSummary.Builder summaryBuilder;
    private final Predicate<ActionAnalysisMetadata> actionMnemonicMatcher;

    public PrintActionRunner(
        boolean compileOneDependency,
        OptionsParsingResult options,
        OutErr outErr,
        List<String> requestedTargets,
        final Set<String> printActionMnemonics) {
      this.compileOneDependency = compileOneDependency;
      this.options = options;
      this.outErr = outErr;
      this.requestedTargets = requestedTargets;
      keepGoing = options.getOptions(KeepGoingOption.class).keepGoing;
      summaryBuilder = ExtraActionSummary.newBuilder();
      actionMnemonicMatcher = new Predicate<ActionAnalysisMetadata>() {
        @Override
        public boolean apply(ActionAnalysisMetadata action) {
          return printActionMnemonics.isEmpty()
              || printActionMnemonics.contains(action.getMnemonic());
        }
      };
    }

    private ExitCode printActionsForTargets(CommandEnvironment env) {
      BuildResult result = gatherActionsForTargets(env, requestedTargets);
      if (result == null) {
        return ExitCode.PARSING_FAILURE;
      }
      if (hasFatalBuildFailure(result)) {
        env.getReporter().handle(Event.error("Build failed when printing actions"));
        return result.getExitCondition();
      }
      String action = TextFormat.printToString(summaryBuilder);
      if (!action.isEmpty()) {
        outErr.printOut(action);
        return result.getExitCondition();
      } else {
        env.getReporter().handle(Event.error("no actions to print were found"));
        return ExitCode.PARSING_FAILURE;
      }
    }

    private BuildResult gatherActionsForTargets(CommandEnvironment env, List<String> targets) {
      BlazeRuntime runtime = env.getRuntime();
      String commandName = PrintActionCommand.this.getClass().getAnnotation(Command.class).name();
      BuildRequest request = BuildRequest.create(commandName, options,
          runtime.getStartupOptionsProvider(),
          targets, outErr, env.getCommandId(), env.getCommandStartTime());
      BuildResult result = new BuildTool(env).processRequest(request, null);
      if (hasFatalBuildFailure(result)) {
        return result;
      }

      ActionGraph actionGraph = env.getSkyframeExecutor().getActionGraph(env.getReporter());

      for (ConfiguredTarget configuredTarget : result.getActualTargets()) {
        NestedSet<Artifact> filesToCompile = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
        OutputGroupInfo outputGroupInfo = OutputGroupInfo.get(configuredTarget);
        if (outputGroupInfo != null) {
          filesToCompile =
              outputGroupInfo.getOutputGroup(OutputGroupInfo.FILES_TO_COMPILE);
        }
        if (!filesToCompile.isEmpty()) {
          try {
            if (compileOneDependency) {
              gatherActionsForFiles(
                  configuredTarget,
                  env,
                  actionGraph,
                  env.getSkyframeExecutor().getActionKeyContext(),
                  targets);
            } else {
              Target target = null;
              try {
                target =
                    env.getPackageManager()
                        .getTarget(env.getReporter(), configuredTarget.getLabel());
              } catch (NoSuchTargetException | NoSuchPackageException | InterruptedException e) {
                env.getReporter().handle(Event.error("Failed to find target to gather actions."));
                return null;
              }
              gatherActionsForTarget(
                  configuredTarget,
                  target,
                  actionGraph,
                  env.getSkyframeExecutor().getActionKeyContext());
            }
          } catch (CommandLineExpansionException e) {
            env.getReporter().handle(Event.error(null, "Error expanding command line: " + e));
            return null;
          }
        } else {
          // TODO(rbraunstein): If a source is a member of a genrule and a cc_library don't
          // trigger this
          env.getReporter().handle(Event.error(
              null, configuredTarget + " is not a supported target kind"));
          return null;
        }
      }
      return result;
    }

    private BuildResult gatherActionsForFiles(
        ConfiguredTarget configuredTarget,
        CommandEnvironment env,
        ActionGraph actionGraph,
        ActionKeyContext actionKeyContext,
        List<String> files)
        throws CommandLineExpansionException {
      Set<String> filesDesired = new LinkedHashSet<>(files);
      ActionFilter filter = new DefaultActionFilter(filesDesired, actionMnemonicMatcher);

      gatherActionsForFile(configuredTarget, filter, env, actionGraph, actionKeyContext);
      return null;
    }

    private void gatherActionsForTarget(
        ConfiguredTarget configuredTarget,
        Target target,
        ActionGraph actionGraph,
        ActionKeyContext actionKeyContext)
        throws CommandLineExpansionException {
      if (!(target instanceof Rule)) {
        return;
      }

      PrintActionVisitor visitor = new PrintActionVisitor(actionGraph, configuredTarget,
          actionMnemonicMatcher);

      // TODO(jvg): do we want to support ruleConfiguredTarget.getOutputArtifacts()?
      // We do for extra actions, but as we're past the action graph building phase,
      // we cannot call it without risking to trigger creation of OutputArtifacts post
      // graph building phase (not allowed). Right now we do not need them for our scenarios.
      visitor.visitWhiteNodes(configuredTarget.getProvider(FileProvider.class).getFilesToBuild());

      Iterable<ActionAnalysisMetadata> actions = visitor.getActions();
      for (ActionAnalysisMetadata action : actions) {
        if (action instanceof Action) {
          DetailedExtraActionInfo.Builder detail = DetailedExtraActionInfo.newBuilder();
          detail.setAction(((Action) action).getExtraActionInfo(actionKeyContext));
          summaryBuilder.addAction(detail);
        }
      }
    }

    /**
     * Looks for files to compile in the given configured target and outputs the corresponding
     * extra_action if the filter evaluates to {@code true}.
     */
    private void gatherActionsForFile(
        ConfiguredTarget configuredTarget,
        ActionFilter filter,
        CommandEnvironment env,
        ActionGraph actionGraph,
        ActionKeyContext actionKeyContext)
        throws CommandLineExpansionException {
      NestedSet<Artifact> artifacts = OutputGroupInfo.get(configuredTarget)
          .getOutputGroup(OutputGroupInfo.FILES_TO_COMPILE);

      if (artifacts.isEmpty()) {
        return;
      }

      for (Artifact artifact : artifacts) {
        ActionAnalysisMetadata action = actionGraph.getGeneratingAction(artifact);
        if (filter.shouldOutput(action, configuredTarget, env)) {
          if (action instanceof Action) {
            DetailedExtraActionInfo.Builder detail = DetailedExtraActionInfo.newBuilder();
            detail.setAction(((Action) action).getExtraActionInfo(actionKeyContext));
            summaryBuilder.addAction(detail);
          }
        }
      }
    }

    private boolean hasFatalBuildFailure(BuildResult result) {
      return result.getActualTargets() == null || (!result.getSuccess() && !keepGoing);
    }
  }

  /** Filter for extra actions. */
  private interface ActionFilter {
    /** Returns true if the given action is not null and should be printed. */
    boolean shouldOutput(
        ActionAnalysisMetadata action, ConfiguredTarget configuredTarget, CommandEnvironment env);
  }

  /**
   * C++ headers are not plain vanilla action inputs: they do not show up in Action.getInputs(),
   * since the actual set of header files is the one discovered during include scanning.
   *
   * <p>However, since there is a scheduling dependency on the header files, we can use the system
   * to implement said scheduling dependency to figure them out. Thus, we go a-fishing in the action
   * graph reaching through error propagating middlemen: one of these exists for each {@code
   * CcCompilationContext} in the transitive closure of the rule.
   */
  private static void expandRecursiveHelper(
      ActionGraph actionGraph,
      Iterable<Artifact> artifacts,
      Set<Artifact> visited,
      Set<Artifact> result) {
    for (Artifact artifact : artifacts) {
      if (!visited.add(artifact)) {
        continue;
      }
      if (!artifact.isMiddlemanArtifact()) {
        result.add(artifact);
        continue;
      }

      ActionAnalysisMetadata middlemanAction = actionGraph.getGeneratingAction(artifact);
      if (middlemanAction.getActionType() != MiddlemanType.ERROR_PROPAGATING_MIDDLEMAN) {
        continue;
      }

      expandRecursiveHelper(actionGraph, middlemanAction.getInputs(), visited, result);
    }
  }

  private static void expandRecursive(ActionGraph actionGraph, Iterable<Artifact> artifacts,
      Set<Artifact> result) {
    expandRecursiveHelper(actionGraph, artifacts, Sets.<Artifact>newHashSet(), result);
  }

  /**
   * A stateful filter that keeps track of which files have already been covered. This makes it such
   * that blaze only prints out one action protobuf per file. This is important for headers. In
   * addition, this also handles C++ header files, which are not considered to be action inputs by
   * blaze (due to include scanning).
   *
   * <p>
   * As caveats, this only works for files that are given as proper relative paths, rather than
   * using target syntax, and only if the current working directory is the client root.
   */
  private static class DefaultActionFilter implements ActionFilter {
    private final Set<String> filesDesired;
    private final Predicate<ActionAnalysisMetadata> actionMnemonicMatcher;

    private DefaultActionFilter(Set<String> filesDesired,
        Predicate<ActionAnalysisMetadata> actionMnemonicMatcher) {
      this.filesDesired = filesDesired;
      this.actionMnemonicMatcher = actionMnemonicMatcher;
    }

    @Override
    public boolean shouldOutput(
        ActionAnalysisMetadata action, ConfiguredTarget configuredTarget, CommandEnvironment env) {
      if (action == null) {
        return false;
      }
      // Check all the inputs for the configured target against the file we want argv for.
      Set<Artifact> expandedArtifacts = Sets.newHashSet();
      expandRecursive(
          env.getSkyframeExecutor().getActionGraph(env.getReporter()),
          action.getInputs(),
          expandedArtifacts);
      for (Artifact input : expandedArtifacts) {
        if (filesDesired.remove(input.getRootRelativePath().getSafePathString())) {
          return actionMnemonicMatcher.apply(action);
        }
      }

      // C++ header files show up in the dependency on the Target, but not the ConfiguredTarget, so
      // we also check the target's header files there.
      RuleConfiguredTarget ruleConfiguredTarget = (RuleConfiguredTarget) configuredTarget;
      Rule rule;
      try {
        rule =
            (Rule)
                env.getPackageManager().getTarget(env.getReporter(), configuredTarget.getLabel());
      } catch (NoSuchTargetException | NoSuchPackageException | InterruptedException e) {
        env.getReporter().handle(Event.error("Failed to find target to determine output."));
        return false;
      }
      if (!rule.isAttrDefined("hdrs", BuildType.LABEL_LIST)) {
        return false;
      }
      List<Label> hdrs =
          ConfiguredAttributeMapper.of(rule, ruleConfiguredTarget.getConfigConditions())
              .get("hdrs", BuildType.LABEL_LIST);
      if (hdrs != null) {
        for (Label hdrLabel : hdrs) {
          if (filesDesired.remove(hdrLabel.toPathFragment().getPathString())) {
            return actionMnemonicMatcher.apply(action);
          }
        }
      }
      return false; // no match
    }
  }
}
