// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8;

import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringForTesting.getCompanionClassNameSuffix;
import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.Disassemble.DisassembleCommand;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.OffOrAuto;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;

public abstract class D8IncrementalRunExamplesAndroidOTest
    extends RunExamplesAndroidOTest<D8Command.Builder> {

  abstract class D8IncrementalTestRunner extends TestRunner<D8IncrementalTestRunner> {

    private final List<Consumer<D8TestBuilder>> testBuilderConsumers = new ArrayList<>();

    D8IncrementalTestRunner(String testName, String packageName, String mainClass) {
      super(testName, packageName, mainClass);
    }

    D8IncrementalTestRunner withBuilder(Consumer<D8TestBuilder> consumer) {
      testBuilderConsumers.add(consumer);
      return this;
    }

    @Override
    D8IncrementalTestRunner withMinApiLevel(AndroidApiLevel minApiLevel) {
      return withBuilder(builder -> builder.setMinApi(minApiLevel));
    }

    @Override
    void build(
        Path testJarFile, Path out, Box<SyntheticItemsTestUtils> syntheticItemsBox, OutputMode mode)
        throws Throwable {
      assert mode == OutputMode.DexIndexed;
      Map<String, ProgramResource> files = compileClassesTogether(testJarFile, null);
      mergeDexFiles(Lists.newArrayList(files.values())).writeToZip(out);
    }

    // Dex classes separately.
    SortedMap<String, ProgramResource> compileClassesSeparately(Path testJarFile) throws Throwable {
      TreeMap<String, ProgramResource> fileToResource = new TreeMap<>();
      List<String> classFiles = collectClassFiles(testJarFile);
      for (String classFile : classFiles) {
        D8TestCompileResult compileResult =
            compileClassFilesInIntermediate(
                testJarFile, Collections.singletonList(classFile), null, OutputMode.DexIndexed);
        assert compileResult.getApp().getDexProgramResourcesForTesting().size() == 1;
        fileToResource.put(
            makeRelative(testJarFile, Paths.get(classFile)).toString(),
            compileResult.getApp().getDexProgramResourcesForTesting().get(0));
      }
      return fileToResource;
    }

    // Dex classes in one D8 invocation.
    SortedMap<String, ProgramResource> compileClassesTogether(Path testJarFile, Path output)
        throws Throwable {
      TreeMap<String, ProgramResource> fileToResource = new TreeMap<>();
      List<String> classFiles = collectClassFiles(testJarFile);
      D8TestCompileResult compileResult =
          compileClassFilesInIntermediate(
              testJarFile, classFiles, output, OutputMode.DexFilePerClassFile);
      SyntheticItemsTestUtils syntheticItems = compileResult.getSyntheticItems();
      for (ProgramResource resource : compileResult.getApp().getDexProgramResourcesForTesting()) {
        Set<String> descriptors = resource.getClassDescriptors();
        String mainClassDescriptor = compileResult.getApp().getPrimaryClassDescriptor(resource);
        Assert.assertNotNull(mainClassDescriptor);
        for (String descriptor : descriptors) {
          // classes are either lambda classes used by the main class, companion classes of the main
          // interface, the main class/interface, or for JDK9, desugaring of try-with-resources.
          ClassReference reference = Reference.classFromDescriptor(descriptor);
          Assert.assertTrue(
              descriptor.endsWith(getCompanionClassNameSuffix() + ";")
                  || syntheticItems.isExternalApiOutlineClass(reference)
                  || syntheticItems.isExternalTwrCloseMethod(reference)
                  || syntheticItems.isMaybeExternalSuppressedExceptionMethod(reference)
                  || syntheticItems.isExternalLambda(reference)
                  || syntheticItems.isExternalStaticInterfaceCall(reference)
                  || descriptor.equals(mainClassDescriptor));
        }
        String classDescriptor =
            DescriptorUtils.getClassBinaryNameFromDescriptor(mainClassDescriptor);
        String classFilePath = classDescriptor + ".class";
        if (File.separatorChar != '/') {
          classFilePath = classFilePath.replace('/', File.separatorChar);
        }
        fileToResource.put(classFilePath, resource);
      }
      return fileToResource;
    }

    private Path makeRelative(Path testJarFile, Path classFile) {
      Path regularParent =
          testJarFile.getParent().resolve(Paths.get("classes"));
      Path legacyParent =
          regularParent.resolve(
              Paths.get(
                  ToolHelper.THIRD_PARTY_DIR, regularParent.getFileName().toString() + "Legacy"));

      if (classFile.startsWith(regularParent)) {
        return regularParent.relativize(classFile);
      }
      Assert.assertTrue(classFile.startsWith(legacyParent));
      return legacyParent.relativize(classFile);
    }

    private List<String> collectClassFiles(Path testJarFile) {
      Map<String, String> result = new HashMap<>();
      // Collect Java 8 classes.
      visitFiles(
          getClassesRoot(testJarFile),
          path -> result.put(path.toFile().getName(), path.toString()));
      // Collect generated classes, overwrite non-generated files.
      visitFiles(
          getGeneratedRoot(testJarFile),
          path -> result.put(path.toFile().getName(), path.toString()));
      // Collect legacy classes.
      visitFiles(
          getLegacyClassesRoot(testJarFile, packageName),
          path -> result.put(path.toFile().getName(), path.toString()));
      List<String> files = new ArrayList<>(result.values());
      Collections.sort(files);
      return files;
    }

    Path getClassesRoot(Path testJarFile) {
      Path parent = testJarFile.getParent();
      return parent.resolve(Paths.get("classes", packageName));
    }

    Path getGeneratedRoot(Path testJarFile) {
      String sourceSet = testJarFile.getParent().toFile().getName();
      return Paths.get(ToolHelper.THIRD_PARTY_DIR, sourceSet + "Generated", packageName);
    }

    D8TestCompileResult compileClassFilesInIntermediate(
        Path testJarFile, List<String> inputFiles, Path outputPath, OutputMode outputMode)
        throws Throwable {
      assert builderTransformations.isEmpty();
      assert outputMode == OutputMode.DexIndexed || outputMode == OutputMode.DexFilePerClassFile;
      return testForD8(Backend.DEX)
          .addProgramFiles(inputFiles.stream().map(Paths::get).collect(Collectors.toList()))
          .addOptionsModification(this::combinedOptionConsumer)
          .apply(
              b -> {
                for (Consumer<D8TestBuilder> testBuilderConsumer : testBuilderConsumers) {
                  testBuilderConsumer.accept(b);
                }
                addClasspathReference(
                    testJarFile, b::addClasspathFiles, b::addClasspathResourceProviders);
                addLibraryReference(
                    androidJarVersion != null || b.getMinApiLevel() >= 0
                        ? ToolHelper.getAndroidJar(
                            androidJarVersion != null
                                ? androidJarVersion.getLevel()
                                : b.getMinApiLevel())
                        : ToolHelper.getMostRecentAndroidJar(),
                    b::addLibraryFiles,
                    b::addLibraryResourceProviders);
                if (outputPath != null) {
                  assert outputMode == OutputMode.DexFilePerClassFile;
                  b.setProgramConsumer(
                      FileUtils.isArchive(outputPath)
                          ? new DexFilePerClassFileConsumer.ArchiveConsumer(outputPath)
                          : new DexFilePerClassFileConsumer.DirectoryConsumer(outputPath));
                } else if (outputMode == OutputMode.DexIndexed) {
                  b.setProgramConsumer(DexIndexedConsumer.emptyConsumer());
                } else {
                  assert outputMode == OutputMode.DexFilePerClassFile;
                  b.setProgramConsumer(DexFilePerClassFileConsumer.emptyConsumer());
                }
              })
          .collectSyntheticItems()
          .setIntermediate(true)
          .compile();
    }

    D8TestCompileResult mergeDexFiles(List<ProgramResource> dexFiles) throws Throwable {
      assert builderTransformations.isEmpty();
      return testForD8()
          .addProgramDexFileData(
              dexFiles.stream()
                  .map(D8IncrementalRunExamplesAndroidOTest::readResource)
                  .collect(Collectors.toList()))
          .addOptionsModification(this::combinedOptionConsumer)
          .apply(
              b -> {
                for (Consumer<D8TestBuilder> testBuilderConsumer : testBuilderConsumers) {
                  testBuilderConsumer.accept(b);
                }
              })
          .compile();
    }

    abstract void addClasspathReference(
        Path testJarFile,
        Consumer<Path> pathConsumer,
        Consumer<ClassFileResourceProvider> providerConsumer);

    abstract void addLibraryReference(
        Path location,
        Consumer<Path> pathConsumer,
        Consumer<ClassFileResourceProvider> providerConsumer)
        throws IOException;
  }

  @Test
  public void dexPerClassFileNoDesugaring() throws Throwable {
    String testName = "dexPerClassFileNoDesugaring";
    String testPackage = "incremental";
    String mainClass = "IncrementallyCompiled";

    Path inputJarFile = Paths.get(EXAMPLE_DIR, testPackage + JAR_EXTENSION);

    D8IncrementalTestRunner test = test(testName, testPackage, mainClass);

    Map<String, ProgramResource> compiledSeparately = test.compileClassesSeparately(inputJarFile);
    Map<String, ProgramResource> compiledTogether = test.compileClassesTogether(inputJarFile, null);
    Assert.assertEquals(compiledSeparately.size(), compiledTogether.size());

    for (Map.Entry<String, ProgramResource> entry : compiledSeparately.entrySet()) {
      ProgramResource otherResource = compiledTogether.get(entry.getKey());
      Assert.assertNotNull(otherResource);
      Assert.assertArrayEquals(readResource(entry.getValue()), readResource(otherResource));
    }

    D8TestCompileResult mergedFromCompiledSeparately =
        test.mergeDexFiles(Lists.newArrayList(compiledSeparately.values()));
    D8TestCompileResult mergedFromCompiledTogether =
        test.mergeDexFiles(Lists.newArrayList(compiledTogether.values()));

    // TODO(b/123504206): Add a main method and test the output runs.

    Assert.assertArrayEquals(
        readResource(
            mergedFromCompiledSeparately.getApp().getDexProgramResourcesForTesting().get(0)),
        readResource(
            mergedFromCompiledTogether.getApp().getDexProgramResourcesForTesting().get(0)));
  }

  @Test
  public void dexPerClassFileWithDesugaring() throws Throwable {
    String testName = "dexPerClassFileWithDesugaring";
    String testPackage = "lambdadesugaringnplus";
    String mainClass = "LambdasWithStaticAndDefaultMethods";

    Path inputJarFile = Paths.get(EXAMPLE_DIR, testPackage + JAR_EXTENSION);

    D8IncrementalTestRunner test = test(testName, testPackage, mainClass);
    test.withInterfaceMethodDesugaring(OffOrAuto.Auto);

    D8TestCompileResult mergedFromCompiledSeparately =
        test.mergeDexFiles(
            Lists.newArrayList(test.compileClassesSeparately(inputJarFile).values()));
    D8TestCompileResult mergedFromCompiledTogether =
        test.mergeDexFiles(
            Lists.newArrayList(test.compileClassesTogether(inputJarFile, null).values()));

    Path out1 = mergedFromCompiledTogether.writeToZip();
    ToolHelper.runArtNoVerificationErrors(out1.toString(), testPackage + "." + mainClass);

    Path out2 = mergedFromCompiledSeparately.writeToZip();
    ToolHelper.runArtNoVerificationErrors(out2.toString(), testPackage + "." + mainClass);

    Path dissasemble1 = temp.newFolder().toPath().resolve("disassemble1.txt");
    Path dissasemble2 = temp.newFolder().toPath().resolve("disassemble2.txt");
    Disassemble.disassemble(
        DisassembleCommand.builder().addProgramFiles(out1).setOutputPath(dissasemble1).build());
    Disassemble.disassemble(
        DisassembleCommand.builder().addProgramFiles(out2).setOutputPath(dissasemble2).build());
    String content1 = StringUtils.join("\n", Files.readAllLines(dissasemble1));
    String content2 = StringUtils.join("\n", Files.readAllLines(dissasemble2));
    assertEquals(content1, content2);

    Assert.assertArrayEquals(
        readResource(
            mergedFromCompiledSeparately.getApp().getDexProgramResourcesForTesting().get(0)),
        readResource(
            mergedFromCompiledTogether.getApp().getDexProgramResourcesForTesting().get(0)));
  }

  @Test
  public void dexPerClassFileWithDispatchMethods() throws Throwable {
    String testName = "dexPerClassFileWithDispatchMethods";
    String testPackage = "interfacedispatchclasses";
    String mainClass = "TestInterfaceDispatchClasses";

    Path inputJarFile = Paths.get(EXAMPLE_DIR, testPackage + JAR_EXTENSION);

    D8IncrementalTestRunner test = test(testName, testPackage, mainClass);
    test.withInterfaceMethodDesugaring(OffOrAuto.Auto);

    D8TestCompileResult mergedFromCompiledSeparately =
        test.mergeDexFiles(
            Lists.newArrayList(test.compileClassesSeparately(inputJarFile).values()));
    D8TestCompileResult mergedFromCompiledTogether =
        test.mergeDexFiles(
            Lists.newArrayList(test.compileClassesTogether(inputJarFile, null).values()));

    // TODO(b/123504206): This test throws an index out of bounds exception.
    // Re-write or verify running fails in the expected way.
    Assert.assertArrayEquals(
        readResource(
            mergedFromCompiledSeparately.getApp().getDexProgramResourcesForTesting().get(0)),
        readResource(
            mergedFromCompiledTogether.getApp().getDexProgramResourcesForTesting().get(0)));
  }

  @Test
  public void dexPerClassFileOutputFiles() throws Throwable {
    String testName = "dexPerClassFileNoDesugaring";
    String testPackage = "incremental";
    String mainClass = "IncrementallyCompiled";

    Path out = temp.getRoot().toPath();

    Path inputJarFile = Paths.get(EXAMPLE_DIR, testPackage + JAR_EXTENSION);

    D8IncrementalTestRunner test = test(testName, testPackage, mainClass);
    test.compileClassesTogether(inputJarFile, out);

    String[] topLevelDir = out.toFile().list();
    assert topLevelDir != null;
    assertEquals(1, topLevelDir.length);
    assertEquals("incremental", topLevelDir[0]);

    String[] dexFiles = out.resolve(topLevelDir[0]).toFile().list();
    assert dexFiles != null;
    Arrays.sort(dexFiles);

    String[] expectedFileNames = {
        "IncrementallyCompiled$A$AB.dex",
        "IncrementallyCompiled$A.dex",
        "IncrementallyCompiled$B$BA.dex",
        "IncrementallyCompiled$B.dex",
        "IncrementallyCompiled$C.dex",
        "IncrementallyCompiled.dex"
    };
    Arrays.sort(expectedFileNames);

    Assert.assertArrayEquals(expectedFileNames, dexFiles);
  }

  @Override
  abstract D8IncrementalTestRunner test(String testName, String packageName, String mainClass);

  @Override
  protected void testIntermediateWithMainDexList(
      String packageName,
      Path input,
      int expectedMainDexListSize,
      List<String> mainDexClasses,
      boolean hasLambda) {
    // Skip those tests.
    Assume.assumeTrue(false);
  }

  @Override
  protected Path buildDexThroughIntermediate(
      String packageName,
      Path input,
      OutputMode outputMode,
      AndroidApiLevel minApi,
      List<String> mainDexClasses) {
    // tests using this should already been skipped.
    throw new Unreachable();
  }

  static byte[] readResource(ProgramResource resource) {
    try (InputStream input = resource.getByteStream()) {
      return ByteStreams.toByteArray(input);
    } catch (ResourceException e) {
      throw new RuntimeException(e);
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }
}
