/*
 * Copyright 2014 Google LLC
 *
 * 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.auto.value;

import static com.google.common.base.StandardSystemProperty.JAVA_HOME;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import com.google.auto.value.processor.AutoAnnotationProcessor;
import com.google.auto.value.processor.AutoBuilderProcessor;
import com.google.auto.value.processor.AutoOneOfProcessor;
import com.google.auto.value.processor.AutoValueProcessor;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.annotation.processing.Processor;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests that we can compile our AutoValue tests using the Eclipse batch compiler. Since the tests
 * exercise many AutoValue subtleties, the ability to compile them all is a good indication of
 * Eclipse support.
 */
@RunWith(JUnit4.class)
public class CompileWithEclipseTest {
  private static final String SOURCE_ROOT = System.getProperty("basedir");

  @BeforeClass
  public static void setSourceRoot() {
    assertWithMessage("basedir property must be set - test must be run from Maven")
        .that(SOURCE_ROOT)
        .isNotNull();
  }

  public @Rule TemporaryFolder tmp = new TemporaryFolder();

  private static final ImmutableSet<String> IGNORED_TEST_FILES =
      ImmutableSet.of(
          "AutoValueNotEclipseTest.java", "CompileWithEclipseTest.java", "GradleTest.java");

  private static final Predicate<File> JAVA_FILE =
      f -> f.getName().endsWith(".java") && !IGNORED_TEST_FILES.contains(f.getName());

  private static final Predicate<File> JAVA8_TEST =
      f ->
          f.getName().equals("AutoValueJava8Test.java")
              || f.getName().equals("AutoOneOfJava8Test.java")
              || f.getName().equals("EmptyExtension.java");

  @Test
  public void compileWithEclipseJava7() throws Exception {
    compileWithEclipse("7", JAVA_FILE.and(JAVA8_TEST.negate()));
  }

  @Test
  public void compileWithEclipseJava8() throws Exception {
    compileWithEclipse("8", JAVA_FILE);
  }

  private void compileWithEclipse(String version, Predicate<File> predicate) throws IOException {
    File sourceRootFile = new File(SOURCE_ROOT);
    File javaDir = new File(sourceRootFile, "src/main/java");
    File javatestsDir = new File(sourceRootFile, "src/test/java");
    Set<File> sources =
        new ImmutableSet.Builder<File>()
            .addAll(filesUnderDirectory(javaDir, predicate))
            .addAll(filesUnderDirectory(javatestsDir, predicate))
            .build();
    assertThat(sources).isNotEmpty();
    JavaCompiler compiler = new EclipseCompiler();
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
    // This hack is only needed in a Google-internal Java 8 environment where symbolic links make it
    // hard for ecj to find the boot class path. Elsewhere it is unnecessary but harmless. Notably,
    // on Java 9+ there is no rt.jar. There, fileManager.getLocation(PLATFORM_CLASS_PATH) returns
    // null, because the relevant classes are in modules inside
    // fileManager.getLocation(SYSTEM_MODULES).
    File rtJar = new File(JAVA_HOME.value() + "/lib/rt.jar");
    if (rtJar.exists()) {
      List<File> bootClassPath =
          ImmutableList.<File>builder()
              .add(rtJar)
              .addAll(fileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH))
              .build();
      fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
    }
    Iterable<? extends JavaFileObject> sourceFileObjects =
        fileManager.getJavaFileObjectsFromFiles(sources);
    String outputDir = tmp.getRoot().toString();
    ImmutableList<String> options =
        ImmutableList.of(
            "-d",
            outputDir,
            "-s",
            outputDir,
            "-source",
            version,
            "-target",
            version,
            "-warn:-warningToken,-intfAnnotation",
            "-Acom.google.auto.value.AutoBuilderIsUnstable");
    JavaCompiler.CompilationTask task =
        compiler.getTask(null, fileManager, null, options, null, sourceFileObjects);
    // Explicitly supply an empty list of extensions for AutoValueProcessor, because otherwise this
    // test will pick up a test one and get confused.
    AutoValueProcessor autoValueProcessor = new AutoValueProcessor(ImmutableList.of());
    ImmutableList<? extends Processor> processors =
        ImmutableList.of(
            autoValueProcessor,
            new AutoOneOfProcessor(),
            new AutoAnnotationProcessor(),
            new AutoBuilderProcessor());
    task.setProcessors(processors);
    assertWithMessage("Compilation should succeed").that(task.call()).isTrue();
  }

  private static ImmutableSet<File> filesUnderDirectory(File dir, Predicate<File> predicate)
      throws IOException {
    assertWithMessage(dir.toString()).that(dir.isDirectory()).isTrue();
    try (Stream<Path> paths = Files.walk(dir.toPath())) {
      return paths.map(Path::toFile).filter(predicate).collect(toImmutableSet());
    }
  }
}
