// 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.shaking.examples;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import com.android.tools.r8.ArchiveClassFileProvider;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.io.ByteStreams;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;

public class InliningClassVersionTest extends TestBase {

  private final int OLD_VERSION = Opcodes.V1_6;
  private final String BASE_DESCRIPTOR = DescriptorUtils.javaTypeToDescriptor(Base.class.getName());

  private static class Base {

    public static void main(String[] args) {
      System.out.println(Inlinee.foo());
    }
  }

  private static class Inlinee {
    public static String foo() {
      return "Hello from Inlinee!";
    }
  }

  private static class DowngradeVisitor extends ClassVisitor {

    private final int version;

    DowngradeVisitor(ClassVisitor cv, int version) {
      super(Opcodes.ASM6, cv);
      this.version = version;
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      assert version > this.version
          : "Going from " + version + " to " + this.version + " is not a downgrade";
      super.visit(this.version, access, name, signature, superName, interfaces);
    }
  }

  private static byte[] downgradeClass(byte[] classBytes, int version) {
    ClassWriter writer = new ClassWriter(0);
    new ClassReader(classBytes).accept(new DowngradeVisitor(writer, version), 0);
    return writer.toByteArray();
  }

  @Test
  public void test() throws Exception {
    Path inputJar = writeInput();
    assertEquals(OLD_VERSION, getBaseClassVersion(inputJar));
    ProcessResult runInput = run(inputJar);
    assertEquals(0, runInput.exitCode);
    Path outputJar = runR8(inputJar);
    ProcessResult runOutput = run(outputJar);
    assertEquals(runInput.toString(), runOutput.toString());
    assertNotEquals(
        "Inliner did not upgrade classfile version", OLD_VERSION, getBaseClassVersion(outputJar));
  }

  private int getBaseClassVersion(Path jar) throws Exception {
    return getClassVersion(jar, BASE_DESCRIPTOR);
  }

  private int getClassVersion(Path jar, String descriptor) throws Exception {

    class ClassVersionReader extends ClassVisitor {
      private int version = -1;

      private ClassVersionReader() {
        super(Opcodes.ASM6);
      }

      @Override
      public void visit(
          int version,
          int access,
          String name,
          String signature,
          String superName,
          String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        assert version != -1;
        this.version = version;
      }
    }

    byte[] bytes =
        ByteStreams.toByteArray(
            new ArchiveClassFileProvider(jar).getProgramResource(descriptor).getByteStream());
    ClassVersionReader reader = new ClassVersionReader();
    new ClassReader(bytes).accept(reader, 0);
    assert reader.version != -1;
    return reader.version;
  }

  private Path writeInput() throws Exception {
    Path inputJar = temp.getRoot().toPath().resolve("input.jar");
    ClassFileConsumer consumer = new ClassFileConsumer.ArchiveConsumer(inputJar);
    consumer.accept(
        downgradeClass(ToolHelper.getClassAsBytes(Base.class), OLD_VERSION), BASE_DESCRIPTOR, null);
    consumer.accept(
        ToolHelper.getClassAsBytes(Inlinee.class),
        DescriptorUtils.javaTypeToDescriptor(Inlinee.class.getName()),
        null);
    consumer.finished(null);
    return inputJar;
  }

  private ProcessResult run(Path jar) throws Exception {
    return ToolHelper.runJava(jar, Base.class.getName());
  }

  private Path runR8(Path inputJar) throws Exception {
    List<String> keepRule =
        Collections.singletonList(
            "-keep class " + Base.class.getName() + " { public static void main(...); }");
    Path outputJar = temp.getRoot().toPath().resolve("output.jar");
    ToolHelper.runR8(
        R8Command.builder()
            .addProgramFiles(inputJar)
            .addLibraryFiles(Paths.get(ToolHelper.JAVA_8_RUNTIME))
            .addProguardConfiguration(keepRule, Origin.unknown())
            .setOutput(outputJar, OutputMode.ClassFile)
            .build());
    return outputJar;
  }
}
