// 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 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(ToolHelper.getJava8RuntimeJar());
    } else {
      builder.addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm()));
    }
    ToolHelper.runR8(builder.build(), options -> options.invalidDebugInfoFatal = true);
  }
}
