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

import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceException;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;

public class CfLineToMethodMapper {

  private final Map<String, Int2ReferenceOpenHashMap<String>> sourceMethodMapping = new HashMap<>();
  private final AndroidApp inputApp;
  private static final String NAME_DESCRIPTOR_SEPARATOR = ";;";

  public CfLineToMethodMapper(AndroidApp inputApp) {
    this.inputApp = inputApp;
  }

  public String lookupNameAndDescriptor(String binaryName, int lineNumber)
      throws ResourceException {
    if (sourceMethodMapping.isEmpty()) {
      readLineNumbersFromClassFiles();
    }
    Int2ReferenceOpenHashMap<String> lineMappings = sourceMethodMapping.get(binaryName);
    return lineMappings == null ? null : lineMappings.get(lineNumber);
  }

  private void readLineNumbersFromClassFiles() throws ResourceException {
    ClassVisitor classVisitor = new ClassVisitor();
    for (ProgramResourceProvider resourceProvider : inputApp.getProgramResourceProviders()) {
      if (resourceProvider instanceof ArchiveResourceProvider) {
        ArchiveResourceProvider provider = (ArchiveResourceProvider) resourceProvider;
        provider.accept(
            programResource -> {
              try {
                new ClassReader(StreamUtils.StreamToByteArrayClose(programResource.getByteStream()))
                    .accept(classVisitor, ClassReader.SKIP_FRAMES);
              } catch (IOException | ResourceException e) {
                // Intentionally left empty because the addition of inline info for kotlin inline
                // functions is a best effort.
              }
            });
      } else {
        for (ProgramResource programResource : resourceProvider.getProgramResources()) {
          if (programResource.getKind() == Kind.CF) {
            try {
              new ClassReader(StreamUtils.StreamToByteArrayClose(programResource.getByteStream()))
                  .accept(classVisitor, ClassReader.SKIP_FRAMES);
            } catch (IOException e) {
              // Intentionally left empty because the addition of inline info for kotlin inline
              // functions is a best effort.
            }
          }
        }
      }
    }
  }

  public static String getName(String nameAndDescriptor) {
    int index = nameAndDescriptor.indexOf(NAME_DESCRIPTOR_SEPARATOR);
    assert index > 0;
    return nameAndDescriptor.substring(0, index);
  }

  public static String getDescriptor(String nameAndDescriptor) {
    int index = nameAndDescriptor.indexOf(NAME_DESCRIPTOR_SEPARATOR);
    assert index > 0;
    return nameAndDescriptor.substring(index + NAME_DESCRIPTOR_SEPARATOR.length());
  }

  private class ClassVisitor extends org.objectweb.asm.ClassVisitor {

    private Int2ReferenceOpenHashMap<String> currentLineNumberMapping = null;

    private ClassVisitor() {
      super(InternalOptions.ASM_VERSION);
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      super.visit(version, access, name, signature, superName, interfaces);
      currentLineNumberMapping =
          sourceMethodMapping.computeIfAbsent(name, ignored -> new Int2ReferenceOpenHashMap<>());
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String descriptor, String signature, String[] exceptions) {
      return new MethodLineVisitor(
          name + NAME_DESCRIPTOR_SEPARATOR + descriptor, currentLineNumberMapping);
    }
  }

  private static class MethodLineVisitor extends MethodVisitor {

    private final String nameAndDescriptor;
    private final Map<Integer, String> lineMethodMapping;

    private MethodLineVisitor(String nameAndDescriptor, Map<Integer, String> lineMethodMapping) {
      super(InternalOptions.ASM_VERSION);
      this.nameAndDescriptor = nameAndDescriptor;
      this.lineMethodMapping = lineMethodMapping;
    }

    @Override
    public void visitLineNumber(int line, Label start) {
      lineMethodMapping.put(line, nameAndDescriptor);
    }
  }
}
