// Copyright (c) 2022, 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 desugaredlibrary;

import static desugaredlibrary.AsmRewriter.ASM_VERSION;
import static desugaredlibrary.CustomConversionAsmRewriteDescription.CONVERT;
import static desugaredlibrary.CustomConversionAsmRewriteDescription.WRAP_CONVERT;
import static desugaredlibrary.CustomConversionAsmRewriter.CustomConversionVersion.LEGACY;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;

import com.google.common.io.ByteStreams;
import desugaredlibrary.AsmRewriter.MethodTransformer;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Enumeration;
import java.util.Map;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class CustomConversionAsmRewriter {

  public enum CustomConversionVersion {
    LEGACY,
    LATEST
  }

  public CustomConversionAsmRewriter(CustomConversionVersion legacy) {
    this.legacy = legacy;
  }

  private final CustomConversionVersion legacy;
  private final Map<String, String> javaWrapConvertOwnerMap =
      CustomConversionAsmRewriteDescription.getJavaWrapConvertOwnerMap();
  private final Map<String, String> j$WrapConvertOwnerMap =
      CustomConversionAsmRewriteDescription.getJ$WrapConvertOwnerMap();

  public static void generateJars(Path jar, Path outputDirectory) throws IOException {
    for (CustomConversionVersion version : CustomConversionVersion.values()) {
      new CustomConversionAsmRewriter(version).convert(jar, outputDirectory);
    }
  }

  private void convert(Path jar, Path outputDirectory) throws IOException {
    String fileName = jar.getFileName().toString();
    String newFileName =
        fileName.substring(0, fileName.length() - "_raw.jar".length())
            + (legacy == LEGACY ? "_legacy" : "")
            + ".jar";
    Path convertedJar = outputDirectory.resolve(newFileName);
    internalConvert(jar, convertedJar);
  }

  private void internalConvert(Path jar, Path convertedJar) throws IOException {
    OpenOption[] options =
        new OpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
    try (ZipOutputStream out =
        new ZipOutputStream(
            new BufferedOutputStream(Files.newOutputStream(convertedJar, options)))) {
      new CustomConversionAsmRewriter(legacy).convert(jar, out, legacy);
    }
  }

  private void convert(
      Path desugaredLibraryFiles, ZipOutputStream out, CustomConversionVersion legacy)
      throws IOException {
    try (ZipFile zipFile = new ZipFile(desugaredLibraryFiles.toFile(), StandardCharsets.UTF_8)) {
      final Enumeration<? extends ZipEntry> entries = zipFile.entries();
      while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();
        try (InputStream entryStream = zipFile.getInputStream(entry)) {
          handleFile(entry, entryStream, out, legacy);
        }
      }
    }
  }

  private void handleFile(
      ZipEntry entry, InputStream input, ZipOutputStream out, CustomConversionVersion legacy)
      throws IOException {
    if (!entry.getName().endsWith(".class")) {
      return;
    }
    if (legacy == LEGACY
        && (entry.getName().contains("java/nio/file")
            || entry.getName().contains("ApiFlips")
            || entry.getName().contains("java/adapter"))) {
      return;
    }
    final byte[] bytes = ByteStreams.toByteArray(input);
    input.close();
    final byte[] rewrittenBytes = transformInvoke(bytes);
    writeToZipStream(out, entry.getName(), rewrittenBytes, ZipEntry.STORED);
  }

  public static void writeToZipStream(
      ZipOutputStream stream, String entry, byte[] content, int compressionMethod)
      throws IOException {
    int offset = 0;
    int length = content.length;
    CRC32 crc = new CRC32();
    crc.update(content, offset, length);
    ZipEntry zipEntry = new ZipEntry(entry);
    zipEntry.setMethod(compressionMethod);
    zipEntry.setSize(length);
    zipEntry.setCrc(crc.getValue());
    zipEntry.setTime(0);
    stream.putNextEntry(zipEntry);
    stream.write(content, offset, length);
    stream.closeEntry();
  }

  private byte[] transformInvoke(byte[] bytes) {
    return AsmRewriter.transformInvoke(bytes, new CustomConversionRewriter(ASM_VERSION));
  }

  class CustomConversionRewriter extends MethodTransformer {

    protected CustomConversionRewriter(int api) {
      super(api);
    }

    @Override
    public void visitMethodInsn(
        int opcode, String owner, String name, String descriptor, boolean isInterface) {
      if (opcode == INVOKESTATIC && name.equals(WRAP_CONVERT)) {
        convertInvoke(opcode, owner, descriptor, isInterface);
        return;
      }
      super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
    }

    private String extractFirstArg(String descriptor) {
      assert descriptor.startsWith("(L");
      int end = descriptor.indexOf(';');
      assert end > 2;
      return descriptor.substring(2, end);
    }

    private void convertInvoke(int opcode, String owner, String descriptor, boolean isInterface) {
      String firstArg = extractFirstArg(descriptor);
      assert sameBaseName(firstArg, owner);
      if (!javaWrapConvertOwnerMap.containsKey(owner)
          || !j$WrapConvertOwnerMap.containsKey(owner)
          || !(firstArg.startsWith("java") || firstArg.startsWith("j$"))) {
        throw new RuntimeException(
            "Cannot transform wrap_convert method for " + firstArg + " (owner: " + owner + ")");
      }
      if (firstArg.startsWith("java")) {
        String newOwner = javaWrapConvertOwnerMap.get(owner);
        super.visitMethodInsn(opcode, newOwner, CONVERT, descriptor, isInterface);
        return;
      }
      assert firstArg.startsWith("j$");
      String newOwner = j$WrapConvertOwnerMap.get(owner);
      super.visitMethodInsn(opcode, newOwner, CONVERT, descriptor, isInterface);
    }

    private boolean sameBaseName(String firstArg, String owner) {
      assert owner.startsWith("j$");
      if (firstArg.equals(owner)) {
        return true;
      }
      String javaName = owner.replace("j$", "java");
      return firstArg.equals(javaName);
    }
  }
}
