// 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.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.BlazeCommandEventHandler;
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.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,
                BlazeCommandEventHandler.Options.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 {
      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.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);
        getSkyframeExecutor().notifyCommandComplete(env.getReporter());
      }
    } finally {
      System.setOut(origSystemOut);
      System.setErr(origSystemErr);
    }
  }

  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;
  }
}
