// Copyright 2019 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.util;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.devtools.build.lib.analysis.AnalysisOptions;
import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ServerDirectories;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection;
import com.google.devtools.build.lib.buildeventstream.BuildEventProtocolOptions;
import com.google.devtools.build.lib.buildtool.BuildRequest;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
import com.google.devtools.build.lib.buildtool.BuildResult;
import com.google.devtools.build.lib.buildtool.BuildTool;
import com.google.devtools.build.lib.clock.JavaClock;
import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
import com.google.devtools.build.lib.exec.BinTools;
import com.google.devtools.build.lib.exec.ExecutionOptions;
import com.google.devtools.build.lib.exec.local.LocalExecutionOptions;
import com.google.devtools.build.lib.packages.StarlarkSemanticsOptions;
import com.google.devtools.build.lib.pkgcache.LoadingOptions;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.ClientOptions;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.CommandStartEvent;
import com.google.devtools.build.lib.runtime.CommonCommandOptions;
import com.google.devtools.build.lib.runtime.GotOptionsEvent;
import com.google.devtools.build.lib.runtime.KeepGoingOption;
import com.google.devtools.build.lib.runtime.LoadingPhaseThreadsOption;
import com.google.devtools.build.lib.runtime.UiOptions;
import com.google.devtools.build.lib.runtime.commands.BuildCommand;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.sandbox.SandboxOptions;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.build.lib.vfs.OutputService;
import com.google.devtools.common.options.InvocationPolicyEnforcer;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

/**
 * A wrapper for {@link BlazeRuntime} for testing purposes that makes it possible to exercise
 * (most) of the build machinery in integration tests. Note that {@code BlazeCommandDispatcher}
 * is not exercised here.
 */
public class BlazeRuntimeWrapper {
  private final BlazeRuntime runtime;
  private CommandEnvironment env;
  private final EventCollectionApparatus events;
  private boolean commandCreated;

  private BuildRequest lastRequest;
  private BuildResult lastResult;
  private BuildConfigurationCollection configurations;
  private ImmutableSet<ConfiguredTarget> topLevelTargets;

  private OptionsParser optionsParser;
  private ImmutableList.Builder<String> optionsToParse = new ImmutableList.Builder<>();

  private Consumer<EventBus> eventBusReceiver;

  public BlazeRuntimeWrapper(
      EventCollectionApparatus events, ServerDirectories serverDirectories,
      BlazeDirectories directories, BinTools binTools, BlazeRuntime.Builder builder)
          throws Exception {
    this.events = events;
    runtime =
        builder
            .setServerDirectories(serverDirectories)
            .addBlazeModule(
                new BlazeModule() {
                  @Override
                  public void beforeCommand(CommandEnvironment env) {
                    // This only does something interesting for tests that create their own
                    // BlazeCommandDispatcher. :-(
                    if (BlazeRuntimeWrapper.this.env != env) {
                      BlazeRuntimeWrapper.this.env = env;
                      BlazeRuntimeWrapper.this.lastRequest = null;
                      BlazeRuntimeWrapper.this.lastResult = null;
                      resetOptions();
                      env.getEventBus().register(this);
                    }
                  }

                  @Subscribe
                  public void analysisPhaseComplete(AnalysisPhaseCompleteEvent e) {
                    topLevelTargets = ImmutableSet.copyOf(e.getTopLevelTargets());
                  }
                })
            .addBlazeModule(
                new BlazeModule() {
                  @Override
                  public void beforeCommand(CommandEnvironment env) {
                    BlazeRuntimeWrapper.this.events.initExternal(env.getReporter());
                  }
                })
            .build();
    runtime.initWorkspace(directories, binTools);
    optionsParser = createOptionsParser();
  }

  @Command(name = "build", builds = true, help = "", shortDescription = "")
  private static class DummyBuildCommand {}

  public OptionsParser createOptionsParser() {
    Set<Class<? extends OptionsBase>> options =
        new HashSet<>(
            ImmutableList.of(
                BuildRequestOptions.class,
                BuildEventProtocolOptions.class,
                ExecutionOptions.class,
                LocalExecutionOptions.class,
                CommonCommandOptions.class,
                ClientOptions.class,
                LoadingOptions.class,
                AnalysisOptions.class,
                KeepGoingOption.class,
                LoadingPhaseThreadsOption.class,
                PackageCacheOptions.class,
                StarlarkSemanticsOptions.class,
                UiOptions.class,
                SandboxOptions.class));

    for (BlazeModule module : runtime.getBlazeModules()) {
      Iterables.addAll(options, module.getCommonCommandOptions());
      Iterables.addAll(
          options, module.getCommandOptions(DummyBuildCommand.class.getAnnotation(Command.class)));
    }
    options.addAll(runtime.getRuleClassProvider().getConfigurationOptions());
    return OptionsParser.builder().optionsClasses(options).build();
  }

  private void enforceTestInvocationPolicy(OptionsParser parser) {
    InvocationPolicyEnforcer optionsPolicyEnforcer =
        new InvocationPolicyEnforcer(runtime.getModuleInvocationPolicy());
    try {
      optionsPolicyEnforcer.enforce(parser);
    } catch (OptionsParsingException e) {
      throw new IllegalStateException(e);
    }
  }

  public BlazeRuntime getRuntime() {
    return runtime;
  }

  /**
   * If called with a non-null argument, all new EventBuses are posted on creation to the given
   * receiver.
   */
  public void setEventBusReceiver(Consumer<EventBus> receiver) {
    eventBusReceiver = receiver;
  }

  public final CommandEnvironment newCommand() throws Exception {
    return newCommand(BuildCommand.class);
  }

  /** Creates a new command environment; executeBuild does this automatically if you do not. */
  public final CommandEnvironment newCommand(Class<? extends BlazeCommand> buildCommand)
      throws Exception {
    initializeOptionsParser();
    commandCreated = true;
    if (env != null) {
      runtime.afterCommand(env, BlazeCommandResult.exitCode(ExitCode.SUCCESS));
    }

    if (optionsParser == null) {
      throw new IllegalArgumentException("The options parser must be initialized before creating "
          + "a new command environment");
    }

    env =
        runtime
            .getWorkspace()
            .initCommand(
                buildCommand.getAnnotation(Command.class), optionsParser, new ArrayList<>());
    return env;
  }

  /**
   * Returns the command environment. You must call {@link #newCommand()} before calling this
   * method.
   */
  public CommandEnvironment getCommandEnvironment() {
    // In these tests, calls to the CommandEnvironment are not always in correct order; this is OK
    // for unit tests. So return an environment here, that has a forced command id to allow tests to
    // stay simple.
    try {
      env.getCommandId();
    } catch (IllegalArgumentException e) {
      // Ignored, as we know that tests deviate from normal calling order.
    }

    return env;
  }

  public SkyframeExecutor getSkyframeExecutor() {
    return runtime.getWorkspace().getSkyframeExecutor();
  }

  public void resetOptions() {
    optionsToParse = new ImmutableList.Builder<>();
  }

  public void addOptions(String... args) {
    addOptions(ImmutableList.copyOf(args));
  }

  public void addOptions(List<String> args) {
    optionsToParse.addAll(args);
  }

  public ImmutableList<String> getOptions() {
    return optionsToParse.build();
  }

  public <O extends OptionsBase> O getOptions(Class<O> optionsClass) {
    return optionsParser.getOptions(optionsClass);
  }

  protected void finalizeBuildResult(@SuppressWarnings("unused") BuildResult request) {}

  /**
   * Initializes a new options parser, parsing all the options set by {@link
   * #addOptions(String...)}.
   */
  public void initializeOptionsParser() throws OptionsParsingException {
    // Create the options parser and parse all the options collected so far
    optionsParser = createOptionsParser();
    optionsParser.parse(optionsToParse.build());
    // Enforce the test invocation policy once the options have been added
    enforceTestInvocationPolicy(optionsParser);
  }

  public void executeBuild(List<String> targets) throws Exception {
    if (!commandCreated) {
      // If you didn't create a command we do it for you
      newCommand();
    }
    commandCreated = false;
    BuildTool buildTool = new BuildTool(env);
    PrintStream origSystemOut = System.out;
    PrintStream origSystemErr = System.err;
    try {
      Profiler.instance()
          .start(
              ImmutableSet.of(),
              /* stream= */ null,
              /* format= */ null,
              /* outputBase= */ null,
              /* buildID= */ null,
              /* recordAllDurations= */ false,
              new JavaClock(),
              /* execStartTimeNanos= */ 42,
              /* enabledCpuUsageProfiling= */ false,
              /* slimProfile= */ false,
              /* enableActionCountProfile= */ false);
      OutErr outErr = env.getReporter().getOutErr();
      System.setOut(new PrintStream(outErr.getOutputStream(), /*autoflush=*/ true));
      System.setErr(new PrintStream(outErr.getErrorStream(), /*autoflush=*/ true));

      // This cannot go into newCommand, because we hook up the EventCollectionApparatus as a
      // module, and after that ran, further changes to the apparatus aren't reflected on the
      // reporter.
      for (BlazeModule module : getRuntime().getBlazeModules()) {
        module.beforeCommand(env);
      }
      if (eventBusReceiver != null) {
        eventBusReceiver.accept(env.getEventBus());
      }
      env.getEventBus()
          .post(
              new GotOptionsEvent(
                  getRuntime().getStartupOptionsProvider(),
                  optionsParser,
                  InvocationPolicy.getDefaultInstance()));
      // This roughly mimics what BlazeRuntime#beforeCommand does in practice.
      env.throwPendingException();

      // In this test we are allowed to omit the beforeCommand; so force setting of a command
      // id in the CommandEnvironment, as we will need it in a moment even though we deviate from
      // normal calling order.
      try {
        env.getCommandId();
      } catch (IllegalArgumentException e) {
        // Ignored, as we know the test deviates from normal calling order.
      }

      OutputService outputService = null;
      BlazeModule outputModule = null;
      for (BlazeModule module : runtime.getBlazeModules()) {
        OutputService moduleService = module.getOutputService();
        if (moduleService != null) {
          if (outputService != null) {
            throw new IllegalStateException(
                String.format(
                    "More than one module (%s and %s) returns an output service",
                    module.getClass(), outputModule.getClass()));
          }
          outputService = moduleService;
          outputModule = module;
        }
      }
      getSkyframeExecutor().setOutputService(outputService);
      env.setOutputServiceForTesting(outputService);

      env.getEventBus()
          .post(
              new CommandStartEvent(
                  "build",
                  env.getCommandId(),
                  env.getBuildRequestId(),
                  env.getClientEnv(),
                  env.getWorkingDirectory(),
                  env.getDirectories(),
                  0));

      lastRequest = createRequest("build", targets);
      lastResult = new BuildResult(lastRequest.getStartTime());
      boolean success = false;

      for (BlazeModule module : getRuntime().getBlazeModules()) {
        env.getSkyframeExecutor().injectExtraPrecomputedValues(module.getPrecomputedValues());
      }

      try {
        try (SilentCloseable c = Profiler.instance().profile("setupPackageCache")) {
          env.setupPackageCache(lastRequest);
        }
        buildTool.buildTargets(lastRequest, lastResult, null);
        success = true;
      } finally {
        env
            .getTimestampGranularityMonitor()
            .waitForTimestampGranularity(lastRequest.getOutErr());
        this.configurations = lastResult.getBuildConfigurationCollection();
        finalizeBuildResult(lastResult);
        buildTool.stopRequest(
            lastResult,
            null,
            success ? ExitCode.SUCCESS : ExitCode.BUILD_FAILURE,
            /*startSuspendCount=*/ 0);
        getSkyframeExecutor().notifyCommandComplete(env.getReporter());
      }
    } finally {
      System.setOut(origSystemOut);
      System.setErr(origSystemErr);
      Profiler.instance().stop();
    }
  }

  public BuildRequest createRequest(String commandName, List<String> targets) {
    return BuildRequest.create(
        commandName,
        optionsParser,
        null,
        targets,
        env.getReporter().getOutErr(),
        env.getCommandId(),
        runtime.getClock().currentTimeMillis());
  }

  public BuildRequest getLastRequest() {
    return lastRequest;
  }

  public BuildResult getLastResult() {
    return lastResult;
  }

  public BuildConfigurationCollection getConfigurationCollection() {
    return configurations;
  }

  public ImmutableSet<ConfiguredTarget> getTopLevelTargets() {
    return topLevelTargets;
  }
}
