// Copyright 2018 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.query2.aquery;

import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
import com.google.devtools.build.lib.analysis.AspectValue;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionException;
import com.google.devtools.build.lib.concurrent.NamedForkJoinPool;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.TargetAccessor;
import com.google.devtools.build.lib.skyframe.RuleConfiguredTargetValue;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.ActionGraphDump;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.AqueryConsumingOutputHandler;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.AqueryOutputHandler;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.AqueryOutputHandler.OutputType;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.MonolithicOutputHandler;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.StreamedConsumingOutputHandler;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.StreamedOutputHandler;
import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;

/** Default output callback for aquery, prints proto output. */
public class ActionGraphProtoOutputFormatterCallback extends AqueryThreadsafeCallback {
  // TODO(b/274595070): Clean this up after flag flip.

  // Arbitrarily chosen. Large enough for good performance, small enough not to cause OOMs.
  private static final int BLOCKING_QUEUE_SIZE = Runtime.getRuntime().availableProcessors() * 2;
  private final OutputType outputType;
  private final ActionGraphDump actionGraphDump;
  private final AqueryActionFilter actionFilters;
  private final AqueryOutputHandler aqueryOutputHandler;

  /**
   * Pseudo-arbitrarily chosen buffer size for output. Chosen to be large enough to fit a handful of
   * messages without needing to flush to the underlying output, which may not be buffered.
   */
  private static final int OUTPUT_BUFFER_SIZE = 16384;

  ActionGraphProtoOutputFormatterCallback(
      ExtendedEventHandler eventHandler,
      AqueryOptions options,
      OutputStream out,
      TargetAccessor<KeyedConfiguredTargetValue> accessor,
      OutputType outputType,
      AqueryActionFilter actionFilters) {
    super(eventHandler, options, out, accessor);
    this.outputType = outputType;
    this.actionFilters = actionFilters;
    this.aqueryOutputHandler =
        constructAqueryOutputHandler(outputType, out, printStream, options.parallelAqueryOutput);
    this.actionGraphDump =
        new ActionGraphDump(
            options.includeCommandline,
            options.includeArtifacts,
            this.actionFilters,
            options.includeParamFiles,
            options.deduplicateDepsets,
            options.includeFileWriteContents,
            aqueryOutputHandler,
            eventHandler);
  }

  public static AqueryOutputHandler constructAqueryOutputHandler(
      OutputType outputType, OutputStream out, PrintStream printStream) {
    return constructAqueryOutputHandler(outputType, out, printStream, /* parallelized= */ false);
  }

  public static AqueryOutputHandler constructAqueryOutputHandler(
      OutputType outputType, OutputStream out, PrintStream printStream, boolean parallelized) {
    switch (outputType) {
      case BINARY:
      case TEXT:
        return parallelized
            ? new StreamedConsumingOutputHandler(
                outputType,
                CodedOutputStream.newInstance(out, OUTPUT_BUFFER_SIZE),
                printStream,
                new LinkedBlockingQueue<>(BLOCKING_QUEUE_SIZE))
            : new StreamedOutputHandler(
                outputType, CodedOutputStream.newInstance(out, OUTPUT_BUFFER_SIZE), printStream);
      case JSON:
        return new MonolithicOutputHandler(printStream);
    }
    // The above cases are exhaustive.
    throw new AssertionError("Wrong output type: " + outputType);
  }

  @Override
  public String getName() {
    return outputType.formatName();
  }

  @Override
  public void close(boolean failFast) throws IOException {
    if (!failFast) {
      try (SilentCloseable c = Profiler.instance().profile("aqueryOutputHandler.close")) {
        aqueryOutputHandler.close();
      }
    }
  }

  @Override
  public void processOutput(Iterable<KeyedConfiguredTargetValue> partialResult)
      throws IOException, InterruptedException {
    if (options.parallelAqueryOutput
        && aqueryOutputHandler instanceof AqueryConsumingOutputHandler) {
      processOutputInParallel(partialResult);
      return;
    }

    try (SilentCloseable c = Profiler.instance().profile("process partial result")) {
      // Enabling includeParamFiles should enable includeCommandline by default.
      options.includeCommandline |= options.includeParamFiles;

      for (KeyedConfiguredTargetValue keyedConfiguredTargetValue : partialResult) {
        processSingleEntry(keyedConfiguredTargetValue);
      }
    } catch (CommandLineExpansionException | TemplateExpansionException e) {
      throw new IOException(e.getMessage());
    }
  }

  private void processSingleEntry(KeyedConfiguredTargetValue keyedConfiguredTargetValue)
      throws CommandLineExpansionException,
          InterruptedException,
          IOException,
          TemplateExpansionException {
    ConfiguredTargetValue configuredTargetValue =
        keyedConfiguredTargetValue.getConfiguredTargetValue();
    if (!(configuredTargetValue instanceof RuleConfiguredTargetValue)) {
      // We have to include non-rule values in the graph to visit their dependencies, but they
      // don't have any actions to print out.
      return;
    }
    actionGraphDump.dumpConfiguredTarget((RuleConfiguredTargetValue) configuredTargetValue);
    if (options.useAspects) {
      for (AspectValue aspectValue : accessor.getAspectValues(keyedConfiguredTargetValue)) {
        actionGraphDump.dumpAspect(aspectValue, configuredTargetValue);
      }
    }
  }

  private void processOutputInParallel(Iterable<KeyedConfiguredTargetValue> partialResult)
      throws IOException, InterruptedException {
    AqueryConsumingOutputHandler aqueryConsumingOutputHandler =
        (AqueryConsumingOutputHandler) aqueryOutputHandler;
    try (SilentCloseable c = Profiler.instance().profile("process partial result")) {
      // Enabling includeParamFiles should enable includeCommandline by default.
      options.includeCommandline |= options.includeParamFiles;
      ForkJoinPool executor =
          NamedForkJoinPool.newNamedPool("aquery", Runtime.getRuntime().availableProcessors());

      try {
        Future<Void> consumerFuture = executor.submit(aqueryConsumingOutputHandler.startConsumer());
        List<Future<Void>> futures = executor.invokeAll(toTasks(partialResult));
        for (Future<Void> future : futures) {
          future.get();
        }
        aqueryConsumingOutputHandler.stopConsumer(/* discardRemainingTasks= */ false);
        // Get any possible exception from the consumer.
        consumerFuture.get();
      } catch (ExecutionException e) {
        aqueryConsumingOutputHandler.stopConsumer(/* discardRemainingTasks= */ true);
        Throwable cause = Throwables.getRootCause(e);
        if (cause instanceof CommandLineExpansionException
            || cause instanceof TemplateExpansionException) {
          // This is kinda weird, but keeping it in line with the status quo for now.
          // TODO(b/266179316): Clean this up.
          throw new IOException(cause.getMessage());
        }
        Throwables.propagateIfPossible(cause, IOException.class);
        Throwables.propagateIfPossible(cause, InterruptedException.class);
        throw new IllegalStateException("Unexpected exception type: ", e);
      } finally {
        executor.shutdown();
      }
    }
  }

  private ImmutableList<AqueryOutputTask> toTasks(Iterable<KeyedConfiguredTargetValue> values) {
    ImmutableList.Builder<AqueryOutputTask> tasks = ImmutableList.builder();
    for (KeyedConfiguredTargetValue value : values) {
      tasks.add(new AqueryOutputTask(value));
    }
    return tasks.build();
  }

  private final class AqueryOutputTask implements Callable<Void> {

    private final KeyedConfiguredTargetValue keyedConfiguredTargetValue;

    AqueryOutputTask(KeyedConfiguredTargetValue keyedConfiguredTargetValue) {
      this.keyedConfiguredTargetValue = keyedConfiguredTargetValue;
    }

    @Override
    public Void call()
        throws CommandLineExpansionException,
            TemplateExpansionException,
            IOException,
            InterruptedException {
      processSingleEntry(keyedConfiguredTargetValue);
      return null;
    }
  }
}
