// 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.blackbox.tests.workspace;

import static com.google.common.truth.Truth.assertThat;

import com.google.devtools.build.lib.bazel.repository.DecompressorDescriptor;
import com.google.devtools.build.lib.bazel.repository.TarFunction;
import com.google.devtools.build.lib.blackbox.framework.BlackBoxTestEnvironment;
import com.google.devtools.build.lib.blackbox.framework.BuilderRunner;
import com.google.devtools.build.lib.blackbox.framework.PathUtils;
import com.google.devtools.build.lib.blackbox.junit.AbstractBlackBoxTest;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.util.FileSystems;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.junit.Test;

/**
 * Test that the embedded Starlark code is compliant with --all_incompatible_changes. To replace
 * bazel_embedded_skylark_test.sh.
 */
public class BazelEmbeddedSkylarkBlackBoxTest extends AbstractBlackBoxTest {

  private static final String HELLO_FROM_EXTERNAL_REPOSITORY = "Hello from external repository!";
  private static final String HELLO_FROM_MAIN_REPOSITORY = "Hello from main repository!";

  @Test
  public void testPkgTar() throws Exception {
    context().write("main/WORKSPACE", BlackBoxTestEnvironment.getWorkspaceWithDefaultRepos());
    context().write("main/foo.txt", "Hello World");
    context().write("main/bar.txt", "Hello World, again");
    context()
        .write(
            "main/BUILD",
            "load(\"@bazel_tools//tools/build_defs/pkg:pkg.bzl\", \"pkg_tar\")",
            "pkg_tar(name = \"data\", srcs = ['foo.txt', 'bar.txt'],)");

    BuilderRunner bazel = bazel();
    bazel.build("...");

    Path dataTarPath = context().resolveBinPath(bazel, "main/data.tar");
    assertThat(Files.exists(dataTarPath)).isTrue();

    Path directory = decompress(dataTarPath);
    assertThat(directory.toFile().exists()).isTrue();

    Map<String, Path> map =
        Arrays.stream(Objects.requireNonNull(directory.toFile().listFiles()))
            .collect(Collectors.toMap(File::getName, file -> Paths.get(file.getAbsolutePath())));

    WorkspaceTestUtils.assertLinesExactly(map.get("foo.txt"), "Hello World");
    WorkspaceTestUtils.assertLinesExactly(map.get("bar.txt"), "Hello World, again");
  }

  @Test
  public void testHttpArchive() throws Exception {
    Path repo = context().getTmpDir().resolve("ext_repo");
    RepoWithRuleWritingTextGenerator generator = new RepoWithRuleWritingTextGenerator(repo);
    generator.withOutputText(HELLO_FROM_EXTERNAL_REPOSITORY).setupRepository();

    // file where we will manually copy the built archive
    Path zipFile = context().getTmpDir().resolve("ext_repo.tar");
    assertThat(Files.exists(zipFile)).isFalse();

    context()
        .write(
            "WORKSPACE",
            BlackBoxTestEnvironment.getWorkspaceWithDefaultRepos(),
            String.format(
                "local_repository(name=\"ext_local\", path=\"%s\",)",
                PathUtils.pathForStarlarkFile(repo)),
            String.format(
                "http_archive(name=\"ext\", urls=[\"%s\"],)", PathUtils.pathToFileURI(zipFile)));

    context()
        .write(
            "BUILD",
            RepoWithRuleWritingTextGenerator.loadRule("@ext"),
            RepoWithRuleWritingTextGenerator.callRule(
                "call_from_main", "main_out.txt", HELLO_FROM_MAIN_REPOSITORY));

    // first build the archive and copy it into zipFile
    BuilderRunner bazel = bazel();
    String tarTarget = generator.getPkgTarTarget();
    bazel.build("@ext_local//:" + tarTarget);
    Path packedFile =
        context().resolveBinPath(bazel, String.format("external/ext_local/%s.tar", tarTarget));
    Files.copy(packedFile, zipFile);

    // now build the target from http_archive
    bazel.build("@ext//:" + RepoWithRuleWritingTextGenerator.TARGET);

    Path xPath = context().resolveBinPath(bazel, "external/ext/out");
    WorkspaceTestUtils.assertLinesExactly(xPath, HELLO_FROM_EXTERNAL_REPOSITORY);

    // and use the rule from http_archive in the main repository
    bazel.build("//:call_from_main");

    Path mainOutPath = context().resolveBinPath(bazel, "main_out.txt");
    WorkspaceTestUtils.assertLinesExactly(mainOutPath, HELLO_FROM_MAIN_REPOSITORY);
  }

  private BuilderRunner bazel() {
    // On Mac, set host config to use PY2 because our CI Mac workers don't have a Python 3 runtime.
    // TODO(https://github.com/bazelbuild/continuous-integration/issues/578): Remove this
    // workaround.
    if (System.getProperty("os.name").toLowerCase().startsWith("mac os x")) {
      System.out.println(
          "Setting host Python to PY2 to workaround unavailability of Python 3 on Mac CI");
      return WorkspaceTestUtils.bazel(context())
          .withFlags("--all_incompatible_changes", "--host_force_python=PY2");
    } else {
      return WorkspaceTestUtils.bazel(context()).withFlags("--all_incompatible_changes");
    }
  }

  private Path decompress(Path dataTarPath) throws Exception {
    FileSystem fs = FileSystems.getNativeFileSystem();
    com.google.devtools.build.lib.vfs.Path dataTarPathForDecompress =
        fs.getPath(dataTarPath.toAbsolutePath().toString());

    com.google.devtools.build.lib.vfs.Path directory =
        TarFunction.INSTANCE.decompress(
            DecompressorDescriptor.builder()
                .setArchivePath(dataTarPathForDecompress)
                .setRepositoryPath(dataTarPathForDecompress.getParentDirectory())
                .build());
    return Paths.get(directory.getPathString());
  }

  // TODO(ichern) test tar quoting
}
