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

import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.actions.ActionContext;
import com.google.devtools.build.lib.actions.SpawnStrategy;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.actions.FileWriteActionContext;
import com.google.devtools.build.lib.analysis.actions.LocalTemplateExpansionStrategy;
import com.google.devtools.build.lib.analysis.actions.SymlinkTreeActionContext;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionContext;
import com.google.devtools.build.lib.bugreport.BugReporter;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.exec.BinTools;
import com.google.devtools.build.lib.exec.BlazeExecutor;
import com.google.devtools.build.lib.exec.ExecutionOptions;
import com.google.devtools.build.lib.exec.FileWriteStrategy;
import com.google.devtools.build.lib.exec.ModuleActionContextRegistry;
import com.google.devtools.build.lib.exec.SpawnStrategyRegistry;
import com.google.devtools.build.lib.exec.SpawnStrategyResolver;
import com.google.devtools.build.lib.exec.SymlinkTreeStrategy;
import com.google.devtools.build.lib.runtime.CommonCommandOptions;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.List;

/**
 * Builder for the test instance of the {@link BlazeExecutor} class.
 */
public class TestExecutorBuilder {
  public static final ImmutableList<Class<? extends OptionsBase>> DEFAULT_OPTIONS =
      ImmutableList.of(ExecutionOptions.class, CommonCommandOptions.class);
  private final FileSystem fileSystem;
  private final Path execRoot;
  private Reporter reporter = new Reporter(new EventBus());
  private OptionsParser optionsParser =
      OptionsParser.builder().optionsClasses(DEFAULT_OPTIONS).build();
  private final ModuleActionContextRegistry.Builder actionContextRegistryBuilder =
      ModuleActionContextRegistry.builder();
  private final SpawnStrategyRegistry.Builder strategyRegistryBuilder =
      SpawnStrategyRegistry.builder();

  public TestExecutorBuilder(
      FileSystem fileSystem, BlazeDirectories directories, BinTools binTools) {
    this(fileSystem, directories.getExecRoot(TestConstants.WORKSPACE_NAME), binTools);
  }

  public TestExecutorBuilder(FileSystem fileSystem, Path execRoot, BinTools binTools) {
    this.fileSystem = fileSystem;
    this.execRoot = execRoot;
    addContext(FileWriteActionContext.class, new FileWriteStrategy());
    addContext(TemplateExpansionContext.class, new LocalTemplateExpansionStrategy());
    addContext(SymlinkTreeActionContext.class, new SymlinkTreeStrategy(null, binTools));
    addContext(SpawnStrategyResolver.class, new SpawnStrategyResolver());
  }

  public TestExecutorBuilder setReporter(Reporter reporter) {
    this.reporter = reporter;
    return this;
  }

  public TestExecutorBuilder setOptionsParser(OptionsParser optionsParser) {
    this.optionsParser = optionsParser;
    return this;
  }

  public TestExecutorBuilder parseOptions(String... options) throws OptionsParsingException {
    this.optionsParser.parse(options);
    return this;
  }

  public TestExecutorBuilder parseOptions(List<String> options) throws OptionsParsingException {
    this.optionsParser.parse(options);
    return this;
  }

  /**
   * Makes the given action context available in the execution phase.
   *
   * <p>If two action contexts are registered with the same identifying type and commandline
   * identifier the last registered will take precedence.
   */
  public <T extends ActionContext> TestExecutorBuilder addContext(
      Class<T> identifyingType, T context, String... commandlineIdentifiers) {
    actionContextRegistryBuilder.register(identifyingType, context, commandlineIdentifiers);
    return this;
  }

  /** Makes the given strategy available in the execution phase. */
  public TestExecutorBuilder addStrategy(SpawnStrategy strategy, String... commandlineIdentifiers) {
    strategyRegistryBuilder.registerStrategy(strategy, commandlineIdentifiers);
    return this;
  }

  /**
   * Sets the default strategies to use if none are supplied by the user.
   *
   * <p>Replaces any previously set default strategies.
   */
  public TestExecutorBuilder setDefaultStrategies(String... strategies) {
    strategyRegistryBuilder.setDefaultStrategies(ImmutableList.copyOf(strategies));
    return this;
  }

  public TestExecutorBuilder setExecution(String mnemonic, String strategy) {
    strategyRegistryBuilder.addMnemonicFilter(mnemonic, ImmutableList.of(strategy));
    return this;
  }

  public BlazeExecutor build() throws AbruptExitException {
    SpawnStrategyRegistry strategyRegistry = strategyRegistryBuilder.build();
    addContext(SpawnStrategyRegistry.class, strategyRegistry);
    ModuleActionContextRegistry actionContextRegistry = actionContextRegistryBuilder.build();
    return new BlazeExecutor(
        fileSystem,
        execRoot,
        reporter,
        BlazeClock.instance(),
        BugReporter.defaultInstance(),
        optionsParser,
        actionContextRegistry,
        strategyRegistry);
  }
}
