// 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.buildtool;

import static com.google.common.collect.ImmutableSet.toImmutableSet;

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.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
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.ProviderCollection;
import com.google.devtools.build.lib.analysis.TopLevelArtifactContext;
import com.google.devtools.build.lib.analysis.TopLevelArtifactHelper;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.configuredtargets.OutputFileConfiguredTarget;
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.exec.ExecutionOptions;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.util.io.OutErr;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;

/**
 * Handles --show_result and --experimental_show_artifacts.
 */
class BuildResultPrinter {
  private final CommandEnvironment env;

  BuildResultPrinter(CommandEnvironment env) {
    this.env = env;
  }

  /**
   * Shows the result of the build. Information includes the list of up-to-date and failed targets
   * and list of output artifacts for successful targets
   *
   * <p>This corresponds to the --show_result flag.
   */
  void showBuildResult(
      BuildRequest request,
      BuildResult result,
      Collection<ConfiguredTarget> configuredTargets,
      Collection<ConfiguredTarget> configuredTargetsToSkip,
      ImmutableMap<AspectKey, ConfiguredAspect> aspects) {
    // NOTE: be careful what you print!  We don't want to create a consistency
    // problem where the summary message and the exit code disagree.  The logic
    // here is already complex.
    boolean ok =
        outputTargets(request, result, configuredTargets, configuredTargetsToSkip, aspects);
    if (!ok && !request.getOptions(ExecutionOptions.class).verboseFailures) {
      request
          .getOutErr()
          .printErr("Use --verbose_failures to see the command lines of failed build steps.\n");
    }
  }

  /**
   * Outputs the targets, omitting values with {@code (nothing to build)} when it allows staying
   * under the --show_result limit.
   *
   * <p>This method exits early if there are too many results.
   *
   * @return {@code true} if no errors were detected among the results inspected, this can be a
   *     false positive on early exit.
   */
  private boolean outputTargets(
      BuildRequest request,
      BuildResult result,
      Collection<ConfiguredTarget> configuredTargets,
      Collection<ConfiguredTarget> configuredTargetsToSkip,
      ImmutableMap<AspectKey, ConfiguredAspect> aspects) {
    BlazeRuntime runtime = env.getRuntime();
    String productName = runtime.getProductName();
    PathPrettyPrinter prettyPrinter =
        OutputDirectoryLinksUtils.getPathPrettyPrinter(
            runtime.getRuleClassProvider().getSymlinkDefinitions(),
            request.getBuildOptions().getSymlinkPrefix(productName),
            productName,
            env.getWorkspace(),
            request.getBuildOptions().printWorkspaceInOutputPathsIfNeeded
                ? env.getWorkingDirectory()
                : env.getWorkspace());
    OutErr outErr = request.getOutErr();

    // Splits aspects based on whether they are validation aspects.
    final ImmutableSet<AspectKey> aspectsToPrint;
    final ImmutableList<AspectKey> validationAspects;
    if (request.useValidationAspect()) {
      var aspectsToPrintBuilder = ImmutableSet.<AspectKey>builder();
      var validationAspectsBuilder = ImmutableList.<AspectKey>builder();
      for (AspectKey key : aspects.keySet()) {
        if (Objects.equals(key.getAspectClass().getName(), BuildRequest.VALIDATION_ASPECT_NAME)) {
          validationAspectsBuilder.add(key);
        } else {
          aspectsToPrintBuilder.add(key);
        }
      }
      aspectsToPrint = aspectsToPrintBuilder.build();
      validationAspects = validationAspectsBuilder.build();
    } else {
      aspectsToPrint = aspects.keySet();
      validationAspects = ImmutableList.of();
    }

    Collection<ConfiguredTarget> targetsToPrint = filterTargetsToPrint(configuredTargets);
    TopLevelArtifactContext context = request.getTopLevelArtifactContext();

    // `essentialBudget` tracks the number of non-empty results that can be printed.
    int essentialBudget = request.getBuildOptions().maxResultTargets;

    // Splits the targets we care about into three buckets. Targets are only considered successful
    // if they and their validation aspects succeeded.
    var skipped = new ArrayList<ConfiguredTarget>();
    var succeeded = new ArrayList<ConfiguredTarget>();
    var artifactsToPrintPerTarget = new ArrayList<ArrayList<Artifact>>();
    var failed = new ArrayList<ConfiguredTarget>();
    essentialBudget =
        splitConfiguredTargetsByResultReturnRemaining(
            targetsToPrint,
            result,
            context,
            configuredTargetsToSkip,
            validationAspects,
            skipped,
            succeeded,
            artifactsToPrintPerTarget,
            failed,
            essentialBudget);
    if (essentialBudget < 0) {
      return failed.isEmpty();
    }

    // Splits the aspects we care about into two buckets.
    var successfulAspects = new ArrayList<AspectKey>();
    var failedAspects = new ArrayList<AspectKey>();
    var artifactsToPrintPerAspect = new ArrayList<ArrayList<Artifact>>(successfulAspects.size());
    essentialBudget =
        splitAspectsByResultReturnRemaining(
            aspectsToPrint,
            aspects,
            context,
            result.getSuccessfulAspects(),
            successfulAspects,
            artifactsToPrintPerAspect,
            failedAspects,
            essentialBudget);
    if (essentialBudget < 0) {
      return failed.isEmpty() && failedAspects.isEmpty();
    }

    // Omits "nothing to build" values if it enables staying under --show_result.
    boolean omitNothingToBuild =
        (targetsToPrint.size() + aspectsToPrint.size())
            > request.getBuildOptions().maxResultTargets;

    outputConfiguredTargets(
        outErr,
        prettyPrinter,
        succeeded,
        artifactsToPrintPerTarget,
        failed,
        skipped,
        omitNothingToBuild);
    outputAspects(
        outErr,
        prettyPrinter,
        successfulAspects,
        artifactsToPrintPerAspect,
        failedAspects,
        omitNothingToBuild);

    return failed.isEmpty() && failedAspects.isEmpty();
  }

  private static int splitConfiguredTargetsByResultReturnRemaining(
      Collection<ConfiguredTarget> configuredTargets,
      BuildResult result,
      TopLevelArtifactContext context,
      Collection<ConfiguredTarget> configuredTargetsToSkip,
      ImmutableList<AspectKey> validationAspects,
      ArrayList<ConfiguredTarget> skipped,
      ArrayList<ConfiguredTarget> succeeded,
      ArrayList<ArrayList<Artifact>> artifactsToPrintPerTarget,
      ArrayList<ConfiguredTarget> failed,
      int essentialBudget) {
    ImmutableSet<ConfiguredTargetKey> validationFailures =
        validationAspects.stream()
            .filter(k -> !result.getSuccessfulAspects().contains(k))
            .map(AspectKey::getBaseConfiguredTargetKey)
            .collect(toImmutableSet());
    Collection<ConfiguredTarget> successfulTargets = result.getSuccessfulTargets();
    for (ConfiguredTarget target : configuredTargets) {
      if (configuredTargetsToSkip.contains(target)) {
        skipped.add(target);
        if (--essentialBudget < 0) {
          return essentialBudget;
        }
      } else if (successfulTargets.contains(target)
          && !validationFailures.contains(ConfiguredTargetKey.fromConfiguredTarget(target))) {
        succeeded.add(target);
        ArrayList<Artifact> artifactsToPrint = getArtifactsToPrint(target, context);
        artifactsToPrintPerTarget.add(artifactsToPrint);
        if (!artifactsToPrint.isEmpty()) {
          if (--essentialBudget < 0) {
            return essentialBudget;
          }
        }
      } else {
        failed.add(target);
        if (--essentialBudget < 0) {
          return essentialBudget;
        }
      }
    }
    return essentialBudget;
  }

  private static ArrayList<Artifact> getArtifactsToPrint(
      ProviderCollection target, TopLevelArtifactContext context) {
    var artifacts = new ArrayList<Artifact>();
    // For up-to-date targets report generated artifacts, but only if they have associated action
    // and not middleman artifacts.
    for (Artifact artifact :
        TopLevelArtifactHelper.getAllArtifactsToBuild(target, context)
            .getImportantArtifacts()
            .toList()) {
      if (TopLevelArtifactHelper.shouldDisplay(artifact)) {
        artifacts.add(artifact);
      }
    }
    return artifacts;
  }

  private static int splitAspectsByResultReturnRemaining(
      Collection<AspectKey> aspectsToPrint,
      ImmutableMap<AspectKey, ConfiguredAspect> aspects,
      TopLevelArtifactContext context,
      ImmutableSet<AspectKey> successfulAspects,
      ArrayList<AspectKey> succeeded,
      ArrayList<ArrayList<Artifact>> artifactsToPrintPerAspect,
      ArrayList<AspectKey> failed,
      int essentialBudget) {
    for (AspectKey aspect : aspectsToPrint) {
      if (successfulAspects.contains(aspect)) {
        succeeded.add(aspect);
        ArrayList<Artifact> artifactsToPrint = getArtifactsToPrint(aspects.get(aspect), context);
        artifactsToPrintPerAspect.add(artifactsToPrint);
        if (!artifactsToPrint.isEmpty()) {
          if (--essentialBudget < 0) {
            return essentialBudget;
          }
        }
      } else {
        failed.add(aspect);
        if (--essentialBudget < 0) {
          return essentialBudget;
        }
      }
    }
    return essentialBudget;
  }

  private static void outputConfiguredTargets(
      OutErr outErr,
      PathPrettyPrinter prettyPrinter,
      ArrayList<ConfiguredTarget> succeeded,
      ArrayList<ArrayList<Artifact>> artifactsToPrintPerTarget,
      ArrayList<ConfiguredTarget> failed,
      ArrayList<ConfiguredTarget> skipped,
      boolean omitNothingToBuild) {
    for (ConfiguredTarget target : skipped) {
      outErr.printErr("Target " + target.getLabel() + " was skipped\n");
    }
    for (int i = 0; i < succeeded.size(); ++i) {
      ConfiguredTarget target = succeeded.get(i);
      Label label = target.getLabel();
      ArrayList<Artifact> artifacts = artifactsToPrintPerTarget.get(i);
      if (artifacts.isEmpty()) {
        if (!omitNothingToBuild) {
          outErr.printErr("Target " + label + " up-to-date (nothing to build)\n");
        }
        continue;
      }
      outErr.printErr("Target " + label + " up-to-date:\n");
      for (Artifact artifact : artifacts) {
        outErr.printErrLn(formatArtifactForShowResults(prettyPrinter, artifact));
      }
    }
    for (ConfiguredTarget target : failed) {
      outErr.printErr("Target " + target.getLabel() + " failed to build\n");

      // For failed compilation, it is still useful to examine temp artifacts, (ie, preprocessed and
      // assembler files).
      OutputGroupInfo topLevelProvider = OutputGroupInfo.get(target);
      if (topLevelProvider != null) {
        for (Artifact temp : topLevelProvider.getOutputGroup(OutputGroupInfo.TEMP_FILES).toList()) {
          if (temp.getPath().exists()) {
            outErr.printErrLn(
                "  See temp at " + prettyPrinter.getPrettyPath(temp.getPath().asFragment()));
          }
        }
      }
    }
  }

  private static void outputAspects(
      OutErr outErr,
      PathPrettyPrinter prettyPrinter,
      ArrayList<AspectKey> succeeded,
      ArrayList<ArrayList<Artifact>> artifactsToPrintPerAspect,
      ArrayList<AspectKey> failed,
      boolean omitNothingToBuild) {
    for (int i = 0; i < succeeded.size(); ++i) {
      AspectKey aspect = succeeded.get(i);
      Label label = aspect.getLabel();
      String aspectName = aspect.getAspectClass().getName();
      ArrayList<Artifact> artifacts = artifactsToPrintPerAspect.get(i);
      if (artifacts.isEmpty()) {
        if (!omitNothingToBuild) {
          outErr.printErr(
              "Aspect " + aspectName + " of " + label + " up-to-date (nothing to build)\n");
        }
        continue;
      }
      outErr.printErr("Aspect " + aspectName + " of " + label + " up-to-date:\n");
      for (Artifact artifact : artifacts) {
        outErr.printErrLn(formatArtifactForShowResults(prettyPrinter, artifact));
      }
    }
    for (AspectKey aspect : failed) {
      Label label = aspect.getLabel();
      String aspectName = aspect.getAspectClass().getName();
      outErr.printErr("Aspect " + aspectName + " of " + label + " failed to build\n");
    }
  }

  private static String formatArtifactForShowResults(
      PathPrettyPrinter prettyPrinter, Artifact artifact) {
    return "  " + prettyPrinter.getPrettyPath(artifact.getPath().asFragment());
  }

  /**
   * Prints a flat list of all artifacts built by the passed top-level targets.
   *
   * <p>This corresponds to the --experimental_show_artifacts flag.
   */
  void showArtifacts(
      BuildRequest request,
      Collection<ConfiguredTarget> configuredTargets,
      Collection<ConfiguredAspect> aspects) {

    TopLevelArtifactContext context = request.getTopLevelArtifactContext();
    Collection<ConfiguredTarget> targetsToPrint = filterTargetsToPrint(configuredTargets);

    NestedSetBuilder<Artifact> artifactsBuilder = NestedSetBuilder.stableOrder();
    targetsToPrint.forEach(
        t ->
            artifactsBuilder.addTransitive(
                TopLevelArtifactHelper.getAllArtifactsToBuild(t, context).getImportantArtifacts()));

    aspects.forEach(
        a ->
            artifactsBuilder.addTransitive(
                TopLevelArtifactHelper.getAllArtifactsToBuild(a, context).getImportantArtifacts()));

    OutErr outErr = request.getOutErr();
    outErr.printErrLn("Build artifacts:");

    NestedSet<Artifact> artifacts = artifactsBuilder.build();
    for (Artifact artifact : artifacts.toList()) {
      if (!artifact.isSourceArtifact()) {
        outErr.printErrLn(">>>" + artifact.getPath());
      }
    }
  }

  /**
   * Returns a list of configured targets that should participate in printing.
   *
   * <p>Hidden rules and other inserted targets are ignored.
   */
  private Collection<ConfiguredTarget> filterTargetsToPrint(
      Collection<ConfiguredTarget> configuredTargets) {
    ImmutableList.Builder<ConfiguredTarget> result = ImmutableList.builder();
    for (ConfiguredTarget configuredTarget : configuredTargets) {
      if (!TopLevelArtifactHelper.shouldConsiderForDisplay(configuredTarget)) {
        continue;
      }
      if (configuredTarget instanceof OutputFileConfiguredTarget) {
        // Suppress display of generated files (because they appear underneath
        // their generating rule), EXCEPT those ones which are not part of the
        // filesToBuild of their generating rule (e.g. .par, _deploy.jar
        // files), OR when a user explicitly requests an output file but not
        // its rule.
        TransitiveInfoCollection generatingRule =
            ((OutputFileConfiguredTarget) configuredTarget).getGeneratingRule();
        if (generatingRule
                .getProvider(FileProvider.class)
                .getFilesToBuild()
                .toSet()
                .containsAll(
                    configuredTarget.getProvider(FileProvider.class).getFilesToBuild().toList())
            && configuredTargets.contains(generatingRule)) {
          continue;
        }
      }

      result.add(configuredTarget);
    }
    return result.build();
  }
}
