package io.bazel.kotlin.builder;

import io.bazel.kotlin.builder.utils.CompilationTaskContext;
import io.bazel.kotlin.model.CompilationTaskInfo;
import org.junit.rules.ExternalResource;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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

public abstract class KotlinBuilderResource extends ExternalResource {
  public enum DirectoryType {
    INSTANCE_ROOT("test root", null),
    EXTERNAL("bazel external directory", null),
    /** The rest of the paths are instance relative. */
    SOURCES("sources", Paths.get("sources")),
    CLASSES("compiled classes", Paths.get("classes")),
    GENERATED_CLASSES("generated classes", Paths.get("generated_classes")),
    TEMP("temp directory", Paths.get("temp")),
    SOURCE_GEN("generated sources directory", Paths.get("generated_sources"));

    private static final EnumSet<DirectoryType> INSTANCE_TYPES =
        EnumSet.of(SOURCES, CLASSES, SOURCE_GEN, GENERATED_CLASSES, TEMP);

    final String name;
    private final Path relativePath;

    DirectoryType(String name, Path relativePath) {
      this.name = name;
      this.relativePath = relativePath;
    }
  }

  public abstract static class Dep {
    private Dep() {}

    abstract Stream<Path> compileJars();

    private static class Simple extends Dep {
      private final List<Path> compileJars;

      private Simple(List<Path> compileJars) {
        this.compileJars = compileJars;
      }

      @Override
      Stream<Path> compileJars() {
        return compileJars.stream();
      }
    }

    static Dep merge(Dep... dependencies) {
      return new Simple(
          Stream.of(dependencies).flatMap(Dep::compileJars).collect(Collectors.toList()));
    }

    public static List<String> classpathOf(Dep... dependencies) {
      return merge(dependencies).compileJars().map(Path::toString).collect(Collectors.toList());
    }

    public static Dep simpleOf(String compileJar) {
      return new Simple(Collections.singletonList(toPlatformPath(compileJar).toAbsolutePath()));
    }

    @SuppressWarnings("unused")
    static Dep simpleOf(Path compileJar) {
      return new Simple(Collections.singletonList(compileJar));
    }
  }

  private static final Path
      BAZEL_TEST_DIR = Paths.get(Objects.requireNonNull(System.getenv("TEST_TMPDIR"))),
      EXTERNAL_PATH = Paths.get("external");
  @SuppressWarnings("unused")
  public static Dep
      KOTLIN_ANNOTATIONS =
          Dep.simpleOf("external/com_github_jetbrains_kotlin/lib/annotations-13.0.jar"),
      KOTLIN_STDLIB = Dep.simpleOf("external/com_github_jetbrains_kotlin/lib/kotlin-stdlib.jar"),
      KOTLIN_STDLIB_JDK7 =
          Dep.simpleOf("external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk7.jar"),
      KOTLIN_STDLIB_JDK8 =
          Dep.simpleOf("external/com_github_jetbrains_kotlin/lib/kotlin-stdlib-jdk8.jar");

  private static final AtomicInteger counter = new AtomicInteger(0);
  private Path instanceRoot = null;
  private String label = null;

  KotlinBuilderResource() {}

  abstract CompilationTaskInfo.Builder infoBuilder();

  String label() {
    return Objects.requireNonNull(label);
  }

  Path instanceRoot() {
    return Objects.requireNonNull(instanceRoot);
  }

  @Override
  protected void before() throws Throwable {
    label = "a_test_" + counter.incrementAndGet();
    setTimeout(DEFAULT_TIMEOUT);
    try {
      this.instanceRoot = Files.createDirectory(BAZEL_TEST_DIR.resolve(Paths.get(label)));
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }

    for (DirectoryType instanceType : DirectoryType.INSTANCE_TYPES) {
      try {
        Files.createDirectory(instanceRoot.resolve(instanceType.relativePath));
      } catch (IOException e) {
        throw new RuntimeException("could not create instance directory: " + instanceType.name, e);
      }
    }
  }

  Path directory(DirectoryType type) {
    switch (type) {
      case INSTANCE_ROOT:
        return instanceRoot;
      case EXTERNAL:
        return KotlinBuilderResource.EXTERNAL_PATH;
      case SOURCES:
      case CLASSES:
      case GENERATED_CLASSES:
      case TEMP:
      case SOURCE_GEN:
        return instanceRoot.resolve(type.relativePath);
      default:
        throw new IllegalStateException(type.toString());
    }
  }

  @SuppressWarnings("unused")
  public final void setDebugTags(String... tags) {
    infoBuilder().addAllDebug(Arrays.asList(tags));
  }

  private int DEFAULT_TIMEOUT = 10;
  private int timeoutSeconds = DEFAULT_TIMEOUT;

  /**
   * sets the timeout for the builder tasks.
   *
   * @param timeoutSeconds a timeout in seconds. For debugging purposes it can be set to <= 0 which
   *     means wait indefinitely.
   */
  @SuppressWarnings("WeakerAccess")
  public final void setTimeout(int timeoutSeconds) {
    this.timeoutSeconds = timeoutSeconds;
  }

  <T, R> R runCompileTask(
      CompilationTaskContext context, T task, BiFunction<CompilationTaskContext, T, R> operation) {
    String curDir = System.getProperty("user.dir");
    System.setProperty("user.dir", instanceRoot().toAbsolutePath().toString());
    try {
      CompletableFuture<R> future =
          CompletableFuture.supplyAsync(() -> operation.apply(context, task));
      return timeoutSeconds > 0 ? future.get(timeoutSeconds, TimeUnit.SECONDS) : future.get();

    } catch (TimeoutException e) {
      throw new AssertionError("did not complete in: " + timeoutSeconds);
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      System.setProperty("user.dir", curDir);
    }
  }

  public final void assertFilesExist(DirectoryType dir, String... paths) {
    assertFileExistence(resolved(dir, paths), true);
  }

  public void assertFilesExist(String... paths) {
    assertFileExistence(Stream.of(paths).map(Paths::get), true);
  }

  @SuppressWarnings("unused")
  public final void assertFilesDoNotExist(DirectoryType dir, String... filePath) {
    assertFileExistence(resolved(dir, filePath), false);
  }

  private static void assertFileExistence(Stream<Path> pathStream, boolean shouldexist) {
    pathStream.forEach(
        path -> {
          if (shouldexist)
            assertWithMessage("file did not exist: " + path).that(path.toFile().exists()).isTrue();
          else assertWithMessage("file existed: " + path).that(path.toFile().exists()).isFalse();
        });
  }

  private Stream<Path> resolved(DirectoryType dir, String... filePath) {
    Path directory = directory(dir);
    return Stream.of(filePath).map(f -> directory.resolve(toPlatformPath(f)));
  }

  /**
   * Normalize a path string.
   *
   * @param path a path using '/' as the seperator.
   * @return a path string suitable for the target platform.
   */
  private static Path toPlatformPath(String path) {
    String[] parts = path.split("/");
    return parts.length == 1
        ? Paths.get(parts[0])
        : Paths.get(parts[0], Arrays.copyOfRange(parts, 1, parts.length));
  }

  @SuppressWarnings("unused")
  private Stream<Path> directoryContents(DirectoryType type) {
    try {
      return Files.walk(directory(type)).map(p -> directory(type).relativize(p));
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

  @SuppressWarnings("unused")
  public final void logDirectoryContents(DirectoryType type) {
    System.out.println(
        directoryContents(type)
            .map(Path::toString)
            .collect(Collectors.joining("\n", "directory " + type.name + " contents:\n", "")));
  }
}
