// 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 com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
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.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.InputFileConfiguredTarget;
import com.google.devtools.build.lib.analysis.configuredtargets.OutputFileConfiguredTarget;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.CollectionUtils;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.exec.ExecutionOptions;
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.runtime.CommandEnvironment;
import com.google.devtools.build.lib.skyframe.AspectValue;
import com.google.devtools.build.lib.util.io.OutErr;
import java.util.ArrayList;
import java.util.Collection;

/**
 * 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.
   */
  public void showBuildResult(
      BuildRequest request,
      BuildResult result,
      Collection<ConfiguredTarget> configuredTargets,
      Collection<ConfiguredTarget> configuredTargetsToSkip,
      Collection<AspectValue> 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.

    OutErr outErr = request.getOutErr();
    Collection<ConfiguredTarget> targetsToPrint = filterTargetsToPrint(configuredTargets);
    Collection<AspectValue> aspectsToPrint = filterAspectsToPrint(aspects);
    final boolean success;
    if (aspectsToPrint.isEmpty()) {
      // Suppress summary if --show_result value is exceeded:
      if (targetsToPrint.size() > request.getBuildOptions().maxResultTargets) {
        return;
      }
      // Filter the targets we care about into two buckets:
      Collection<ConfiguredTarget> succeeded = new ArrayList<>();
      Collection<ConfiguredTarget> failed = new ArrayList<>();
      Collection<ConfiguredTarget> successfulTargets = result.getSuccessfulTargets();
      for (ConfiguredTarget target : targetsToPrint) {
        (successfulTargets.contains(target) ? succeeded : failed).add(target);
      }

      // TODO(bazel-team): convert these to a new "SKIPPED" status when ready: b/62191890.
      failed.addAll(configuredTargetsToSkip);

      TopLevelArtifactContext context = request.getTopLevelArtifactContext();
      for (ConfiguredTarget target : succeeded) {
        Label label = target.getLabel();
        // For up-to-date targets report generated artifacts, but only
        // if they have associated action and not middleman artifacts.
        boolean headerFlag = true;
        for (Artifact artifact :
            TopLevelArtifactHelper.getAllArtifactsToBuild(target, context)
                .getImportantArtifacts()) {
          if (shouldPrint(artifact)) {
            if (headerFlag) {
              outErr.printErr("Target " + label + " up-to-date:\n");
              headerFlag = false;
            }
            outErr.printErrLn(formatArtifactForShowResults(artifact, request));
          }
        }
        if (headerFlag) {
          outErr.printErr("Target " + label + " up-to-date (nothing to build)\n");
        }
      }
      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);
        String productName = env.getRuntime().getProductName();
        if (topLevelProvider != null) {
          for (Artifact temp : topLevelProvider.getOutputGroup(OutputGroupInfo.TEMP_FILES)) {
            if (temp.getPath().exists()) {
              outErr.printErrLn(
                  "  See temp at "
                      + OutputDirectoryLinksUtils.getPrettyPath(
                          temp.getPath(),
                          env.getWorkspaceName(),
                          env.getWorkspace(),
                          request.getBuildOptions().getSymlinkPrefix(productName),
                          productName));
            }
          }
        }
      }
      success = failed.isEmpty();
    } else {
      // Suppress summary if --show_result value is exceeded:
      if (aspectsToPrint.size() > request.getBuildOptions().maxResultTargets) {
        return;
      }
      // Filter the targets we care about into two buckets:
      Collection<AspectValue> succeeded = new ArrayList<>();
      Collection<AspectValue> failed = new ArrayList<>();
      Collection<AspectValue> successfulAspects = result.getSuccessfulAspects();
      for (AspectValue aspect : aspectsToPrint) {
        (successfulAspects.contains(aspect) ? succeeded : failed).add(aspect);
      }
      TopLevelArtifactContext context = request.getTopLevelArtifactContext();
      for (AspectValue aspect : succeeded) {
        Label label = aspect.getLabel();
        String aspectName = aspect.getConfiguredAspect().getName();
        boolean headerFlag = true;
        NestedSet<Artifact> importantArtifacts =
            TopLevelArtifactHelper.getAllArtifactsToBuild(aspect, context).getImportantArtifacts();
        for (Artifact importantArtifact : importantArtifacts) {
          if (headerFlag) {
            outErr.printErr("Aspect " + aspectName + " of " + label + " up-to-date:\n");
            headerFlag = false;
          }
          if (shouldPrint(importantArtifact)) {
            outErr.printErrLn(formatArtifactForShowResults(importantArtifact, request));
          }
        }
        if (headerFlag) {
          outErr.printErr(
              "Aspect " + aspectName + " of " + label + " up-to-date (nothing to build)\n");
        }
      }
      for (AspectValue aspect : failed) {
        Label label = aspect.getLabel();
        String aspectName = aspect.getConfiguredAspect().getName();
        outErr.printErr("Aspect " + aspectName + " of " + label + " failed to build\n");
      }
      success = failed.isEmpty();
    }
    if (!success && !request.getOptions(ExecutionOptions.class).verboseFailures) {
      outErr.printErr("Use --verbose_failures to see the command lines of failed build steps.\n");
    }
  }

  private boolean shouldPrint(Artifact artifact) {
    return !artifact.isSourceArtifact() && !artifact.isMiddlemanArtifact();
  }

  private String formatArtifactForShowResults(Artifact artifact, BuildRequest request) {
    String productName = env.getRuntime().getProductName();
    return "  " + OutputDirectoryLinksUtils.getPrettyPath(artifact.getPath(),
        env.getWorkspaceName(), env.getWorkspace(),
        request.getBuildOptions().getSymlinkPrefix(productName), productName);
  }

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

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

    NestedSetBuilder<Artifact> artifactsBuilder = NestedSetBuilder.stableOrder();
    for (ConfiguredTarget target : targetsToPrint) {
      artifactsBuilder.addTransitive(
          TopLevelArtifactHelper.getAllArtifactsToBuild(target, context).getImportantArtifacts());
    }

    for (AspectValue aspect : aspectsToPrint) {
      artifactsBuilder.addTransitive(
          TopLevelArtifactHelper.getAllArtifactsToBuild(aspect, context).getImportantArtifacts());
    }

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

    NestedSet<Artifact> artifacts = artifactsBuilder.build();
    for (Artifact artifact : artifacts) {
      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) {
      // TODO(bazel-team): this is quite ugly. Add a marker provider for this check.
      if (configuredTarget instanceof InputFileConfiguredTarget) {
        // Suppress display of source files (because we do no work to build them).
        continue;
      }
      Target target = null;
      try {
        target = env.getPackageManager().getTarget(env.getReporter(), configuredTarget.getLabel());
      } catch (NoSuchPackageException | NoSuchTargetException | InterruptedException e) {
        env.getReporter()
            .handle(Event.error("Unable to get target when filtering targets to print. " + e));
        continue;
      }
      if (target instanceof Rule) {
        Rule rule = (Rule) target;
        if (rule.getRuleClass().contains("$")) {
          // Suppress display of hidden rules
          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 (CollectionUtils.containsAll(
                generatingRule.getProvider(FileProvider.class).getFilesToBuild(),
                configuredTarget.getProvider(FileProvider.class).getFilesToBuild())
            && configuredTargets.contains(generatingRule)) {
          continue;
        }
      }

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

  private Collection<AspectValue> filterAspectsToPrint(Collection<AspectValue> aspects) {
    return aspects;
  }
}
