// Copyright 2017 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.bazel.e4b.integration;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;

import org.junit.Before;
import org.junit.BeforeClass;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.devtools.bazel.e4b.command.Command;

/** A base class to do integration test that call Bazel */
public abstract class BazelBaseTestCase {

  protected final static Joiner PATH_JOINER = Joiner.on(File.separator);
  protected final static Joiner LINE_JOINER = Joiner.on("\n");

  private static File tmp;
  private static Map<String, File> bazelVersions;
  private static File runfileDirectory = new File(System.getenv("TEST_SRCDIR"));

  private File currentBazel = null;

  /** The current workspace. */
  protected File workspace = null;

  public static class BazelTestCaseException extends Exception {
    private static final long serialVersionUID = 1L;

    private BazelTestCaseException(String message) {
      super(message);
    }
  }

  @BeforeClass
  public static void setUpClass() throws IOException {
    // Get tempdir
    String _tmp = System.getenv("TEST_TMPDIR");
    if (_tmp == null) {
      File p = Files.createTempDirectory("e4b-tests").toFile();
      p.deleteOnExit();
      tmp = p;
    } else {
      tmp = new File(_tmp);
    }
    bazelVersions = new HashMap<>();
  }

  /** Return a file in the runfiles whose path segments are given by the arguments. */
  protected static File getRunfile(String... segments) {
    return new File(PATH_JOINER.join(runfileDirectory, PATH_JOINER.join(segments)));
  }

  private static void unpackBazel(String version)
      throws BazelTestCaseException, IOException, InterruptedException {
    if (!bazelVersions.containsKey(version)) {
      // Get bazel location
      File bazelFile = getRunfile("build_bazel_bazel_" + version.replace('.', '_') + "/bazel");
      if (!bazelFile.exists()) {
        throw new BazelTestCaseException(
            "Bazel version " + version + " not found");
      }
      bazelVersions.put(version, bazelFile);
      // Unzip Bazel
      prepareCommand(tmp,
          ImmutableList.of(bazelVersions.get(version).getCanonicalPath(),
              "--output_user_root=" + tmp,
          "--nomaster_bazelrc",
              "--max_idle_secs=30", "--bazelrc=/dev/null", "help")).run();
    }
  }

  /** Specify with bazel version to use, required before calling bazel. */
  protected void bazelVersion(String version)
      throws BazelTestCaseException, IOException, InterruptedException {
    unpackBazel(version);
    currentBazel = bazelVersions.get(version);
  }

  /** Create a new workspace, previous one can still be used. */
  protected void newWorkspace() throws IOException {
    this.workspace = java.nio.file.Files.createTempDirectory(tmp.toPath(), "workspace").toFile();
    this.scratchFile("WORKSPACE");
  }

  @Before
  public void setUp() throws Exception {
    this.currentBazel = null;
    if (System.getProperty("bazel.version") != null) {
      bazelVersion(System.getProperty("bazel.version"));
    }
    newWorkspace();
  }

  /** Prepare bazel for running, and return the {@link Command} object to run it. */
  protected Command bazel(String... args) throws BazelTestCaseException, IOException {
    return bazel(ImmutableList.copyOf(args));
  }

  /** Prepare bazel for running, and return the {@link Command} object to run it. */
  protected Command bazel(Iterable<String> args) throws BazelTestCaseException, IOException {
    if (currentBazel == null) {
      throw new BazelTestCaseException("Cannot use bazel because no version was specified, "
          + "please call bazelVersion(version) before calling bazel(...).");
    }

    return prepareCommand(workspace,
        ImmutableList.<String>builder()
            .add(currentBazel.getCanonicalPath(), "--output_user_root=" + tmp, "--nomaster_bazelrc",
                "--max_idle_secs=10", "--bazelrc=/dev/null")
            .addAll(args).build());
  }

  /**
   * Copy a file from the runfiles under {@code path} into {@code destpath} under the current
   * workspace.
   */
  protected void copyFromRunfiles(String path, String destpath) throws IOException {
    File origin = getRunfile(path);
    File dest = new File(workspace, destpath);
    if (!dest.getParentFile().exists()) {
      dest.getParentFile().mkdirs();
    }
    Files.copy(origin.toPath(), dest.toPath());
  }

  /**
   * Copy a file from the runfiles under {@code path} into {@code path} under the current workspace.
   */
  protected void copyFromRunfiles(String path) throws IOException {
    copyFromRunfiles(path, path);
  }

  /**
   * Create a file under {@code path} in the current workspace, filling it with the lines given in
   * {@code content}.
   */
  protected void scratchFile(String path, String... content) throws IOException {
    File dest = new File(workspace,path);
    if (!dest.getParentFile().exists()) {
      dest.getParentFile().mkdirs();
    }
    Files.write(dest.toPath(), LINE_JOINER.join(content).getBytes(StandardCharsets.UTF_8));
  }

  private static Command prepareCommand(File folder, Iterable<String> command) throws IOException {
    Command.Builder builder = Command.builder(null).setConsoleName(null).setDirectory(folder);
    builder.addArguments(command);
    builder.setStderrLineSelector((String x) -> {
      return x;
    }).setStdoutLineSelector((String x) -> {
      return x;
    });
    return builder.build();
  }
}
