// 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.sandbox;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.exec.local.LocalEnvProvider;
import com.google.devtools.build.lib.exec.local.WindowsLocalEnvProvider;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxInputs;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.time.Duration;

/** Spawn runner that uses BuildXL Sandbox APIs to execute a local subprocess. */
final class WindowsSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {

  private final SandboxHelpers helpers;
  private final Path execRoot;
  private final PathFragment windowsSandbox;
  private final LocalEnvProvider localEnvProvider;
  private final Duration timeoutKillDelay;

  /**
   * Creates a sandboxed spawn runner that uses the {@code windows-sandbox} tool.
   *
   * @param helpers common tools and state across all spawns during sandboxed execution
   * @param cmdEnv the command environment to use
   * @param timeoutKillDelay an additional grace period before killing timing out commands
   * @param windowsSandboxPath path to windows-sandbox binary
   */
  WindowsSandboxedSpawnRunner(
      SandboxHelpers helpers,
      CommandEnvironment cmdEnv,
      Duration timeoutKillDelay,
      PathFragment windowsSandboxPath) {
    super(cmdEnv);
    this.helpers = helpers;
    this.execRoot = cmdEnv.getExecRoot();
    this.windowsSandbox = windowsSandboxPath;
    this.timeoutKillDelay = timeoutKillDelay;
    this.localEnvProvider = new WindowsLocalEnvProvider(cmdEnv.getClientEnv());
  }

  @Override
  protected SandboxedSpawn prepareSpawn(Spawn spawn, SpawnExecutionContext context)
      throws IOException {
    Path tmpDir = createActionTemp(execRoot);
    Path commandTmpDir = tmpDir.getRelative("work");
    commandTmpDir.createDirectory();
    ImmutableMap<String, String> environment =
        localEnvProvider.rewriteLocalEnv(
            spawn.getEnvironment(), binTools, commandTmpDir.getPathString());

    SandboxInputs readablePaths =
        helpers.processInputFiles(
            context.getInputMapping(
                getSandboxOptions().symlinkedSandboxExpandsTreeArtifactsInRunfilesTree),
            spawn,
            context.getArtifactExpander(),
            execRoot);

    readablePaths.materializeVirtualInputs(execRoot);

    ImmutableSet.Builder<Path> writablePaths = ImmutableSet.builder();
    writablePaths.addAll(getWritableDirs(execRoot, environment));
    for (ActionInput output : spawn.getOutputFiles()) {
      writablePaths.add(execRoot.getRelative(output.getExecPath()));
    }

    Duration timeout = context.getTimeout();

    if (!readablePaths.getSymlinks().isEmpty()) {
      throw new IOException(
          "Windows sandbox does not support unresolved symlinks yet ("
              + Joiner.on(", ").join(readablePaths.getSymlinks().keySet())
              + ")");
    }

    WindowsSandboxUtil.CommandLineBuilder commandLineBuilder =
        WindowsSandboxUtil.commandLineBuilder(windowsSandbox, spawn.getArguments())
            .setWritableFilesAndDirectories(writablePaths.build())
            .setReadableFilesAndDirectories(readablePaths.getFiles())
            .setInaccessiblePaths(getInaccessiblePaths())
            .setUseDebugMode(getSandboxOptions().sandboxDebug)
            .setKillDelay(timeoutKillDelay);

    if (!timeout.isZero()) {
      commandLineBuilder.setTimeout(timeout);
    }

    return new WindowsSandboxedSpawn(execRoot, environment, commandLineBuilder.build());
  }

  private static Path createActionTemp(Path execRoot) throws IOException {
    return execRoot.getRelative(
        java.nio.file.Files.createTempDirectory(
                java.nio.file.Paths.get(execRoot.getPathString()), "windows-sandbox.")
            .getFileName()
            .toString());
  }

  @Override
  public String getName() {
    return "windows-sandbox";
  }
}
