// Copyright (c) 2018, 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.ir;

import static org.junit.Assert.assertEquals;

import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.DescriptorUtils;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Test;

public class PhiDefinitionsTestRunner extends TestBase {

  private ProcessResult runInput;
  private String className = PhiDefinitionsTest.class.getName();

  private Path writeAndRunOriginal() throws IOException {
    Path originalJar = temp.getRoot().toPath().resolve("originput.jar");
    ClassFileConsumer consumer = new ClassFileConsumer.ArchiveConsumer(originalJar);
    for (Class clazz : PhiDefinitionsTest.CLASSES) {
      String descriptor = DescriptorUtils.javaTypeToDescriptor(clazz.getName());
      consumer.accept(ToolHelper.getClassAsBytes(clazz), descriptor, null);
    }
    consumer.finished(null);
    runOriginalJar(originalJar);
    return originalJar;
  }

  private void runOriginalJar(Path originalJar) throws IOException {
    runInput = ToolHelper.runJava(originalJar, className);
    if (runInput.exitCode != 0) {
      System.out.println(runInput);
    }
    assertEquals(0, runInput.exitCode);
  }

  private Path writeAndRunInputJar() throws Exception {
    Path originalJar = writeAndRunOriginal();
    Path inputJar = temp.getRoot().toPath().resolve("input.jar");
    build(originalJar, new ClassFileConsumer.ArchiveConsumer(inputJar));
    runCf(inputJar, className);
    return inputJar;
  }

  private Path writeAndRunDumpJar() throws Exception {
    Path dumpJar = temp.getRoot().toPath().resolve("dump.jar");
    ClassFileConsumer consumer = new ClassFileConsumer.ArchiveConsumer(dumpJar);
    String desc = 'L' + PhiDefinitionsTestDump.INTERNAL_NAME + ';';
    consumer.accept(PhiDefinitionsTestDump.dump(), desc, null);
    String innerDesc = 'L' + PhiDefinitionsTestDump.INNER_INTERNAL_NAME + ';';
    consumer.accept(PhiDefinitionsTestDump.dumpInner(), innerDesc, null);
    consumer.finished(null);
    runOriginalJar(dumpJar);
    return dumpJar;
  }

  @Test
  public void testCf() throws Exception {
    Path outCf = temp.getRoot().toPath().resolve("cf.zip");
    build(writeAndRunInputJar(), new ClassFileConsumer.ArchiveConsumer(outCf));
    runCf(outCf, className);
  }

  @Test
  public void testDex() throws Exception {
    Path outDex = temp.getRoot().toPath().resolve("dex.zip");
    build(writeAndRunInputJar(), new DexIndexedConsumer.ArchiveConsumer(outDex));
    runDex(outDex, className);
  }

  @Test
  public void testCfDump() throws Exception {
    Path outCf = temp.getRoot().toPath().resolve("dump-cf.zip");
    build(writeAndRunDumpJar(), new ClassFileConsumer.ArchiveConsumer(outCf));
    runCf(outCf, className);
  }

  @Test
  public void testDexDump() throws Exception {
    Path outDex = temp.getRoot().toPath().resolve("dump-dex.zip");
    build(writeAndRunDumpJar(), new DexIndexedConsumer.ArchiveConsumer(outDex));
    runDex(outDex, className);
  }

  private void runCf(Path outCf, String className) throws Exception {
    ProcessResult runCf = ToolHelper.runJava(outCf, className);
    assertEquals(runInput.toString(), runCf.toString());
  }

  private void runDex(Path outDex, String className) throws Exception {
    ProcessResult runDex = ToolHelper.runArtNoVerificationErrorsRaw(outDex.toString(), className);
    assertEquals(runInput.stdout, runDex.stdout);
    assertEquals(runInput.exitCode, runDex.exitCode);
  }

  private void build(Path inputJar, ProgramConsumer consumer) throws Exception {
    Builder builder =
        R8Command.builder()
            .setMode(CompilationMode.DEBUG)
            .setProgramConsumer(consumer)
            .addProgramFiles(inputJar);
    if (consumer instanceof ClassFileConsumer) {
      builder.addLibraryFiles(Paths.get(ToolHelper.JAVA_8_RUNTIME));
    } else {
      builder.addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm()));
    }
    ToolHelper.runR8(builder.build(), options -> options.invalidDebugInfoFatal = true);
  }
}
