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

import static com.android.tools.r8.androidapi.AndroidApiDataAccess.constantPoolHash;
import static com.android.tools.r8.androidapi.AndroidApiLevelHashingDatabaseImpl.getNonExistingDescriptor;
import static com.android.tools.r8.androidapi.AndroidApiLevelHashingDatabaseImpl.getUniqueDescriptorForReference;
import static com.android.tools.r8.lightir.ByteUtils.isU2;
import static com.android.tools.r8.lightir.ByteUtils.setBitAtIndex;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.androidapi.AndroidApiDataAccess;
import com.android.tools.r8.androidapi.GenerateCovariantReturnTypeMethodsTest.CovariantMethodsInJarResult;
import com.android.tools.r8.apimodel.AndroidApiVersionsXmlParser.ParsedApiClass;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexLibraryClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.ThrowingBiConsumer;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class AndroidApiHashingDatabaseBuilderGenerator extends TestBase {

  /**
   * Generate the information needed for looking up api level of references in the android.jar. This
   * method will generate one single database file where the format is as follows (uX is X number of
   * unsigned bytes):
   *
   * <pre>
   * constant_pool_size: u4
   * constant_pool:      [constant_pool_size * payload_entry]
   * constant_pool_map:  [0..max_hash(DexString) * payload_entry]
   * api_map:            [0..max_hash(DexReference) * payload_entry]
   * payload             raw data.
   *
   * payload_entry: u4:relative_offset_from_payload_start + u2:length
   * </pre>
   *
   * For hash_definitions and entries see {@code AndroidApiDataAccess}.
   */
  public static void generate(
      List<ParsedApiClass> apiClasses, Path pathToApiLevels, AndroidApiLevel androidJarApiLevel)
      throws Exception {
    Map<ClassReference, Map<DexMethod, AndroidApiLevel>> methodMap = new HashMap<>();
    Map<ClassReference, Map<DexField, AndroidApiLevel>> fieldMap = new HashMap<>();
    Map<ClassReference, ParsedApiClass> lookupMap = new HashMap<>();

    Map<DexReference, AndroidApiLevel> referenceMap = new HashMap<>();

    Path androidJar = ToolHelper.getAndroidJar(androidJarApiLevel);
    AppView<AppInfoWithClassHierarchy> appView =
        computeAppViewWithClassHierarchy(AndroidApp.builder().addLibraryFile(androidJar).build());
    DexItemFactory factory = appView.dexItemFactory();

    CovariantMethodsInJarResult covariantMethodsInJar = CovariantMethodsInJarResult.create();

    for (ParsedApiClass apiClass : apiClasses) {
      Map<DexMethod, AndroidApiLevel> methodsForApiClass = new HashMap<>();
      apiClass.visitMethodReferences(
          (apiLevel, methods) -> {
            methods.forEach(
                method -> methodsForApiClass.put(factory.createMethod(method), apiLevel));
          });
      covariantMethodsInJar.visitCovariantMethodsForHolder(
          apiClass.getClassReference(),
          methodReferenceWithApiLevel -> {
            DexMethod method =
                factory.createMethod(methodReferenceWithApiLevel.getMethodReference());
            if (!methodsForApiClass.containsKey(method)) {
              apiClass.amendCovariantMethod(
                  methodReferenceWithApiLevel.getMethodReference(),
                  methodReferenceWithApiLevel.getApiLevel());
              methodsForApiClass.put(method, methodReferenceWithApiLevel.getApiLevel());
            }
          });
      Map<DexField, AndroidApiLevel> fieldsForApiClass = new HashMap<>();
      apiClass.visitFieldReferences(
          (apiLevel, fields) -> {
            fields.forEach(field -> fieldsForApiClass.put(factory.createField(field), apiLevel));
          });
      methodMap.put(apiClass.getClassReference(), methodsForApiClass);
      fieldMap.put(apiClass.getClassReference(), fieldsForApiClass);
      lookupMap.put(apiClass.getClassReference(), apiClass);

      referenceMap.put(
          factory.createType(apiClass.getClassReference().getDescriptor()), apiClass.getApiLevel());
    }

    for (ParsedApiClass apiClass : apiClasses) {
      computeAllReferencesInHierarchy(
          lookupMap,
          factory,
          factory.createType(apiClass.getClassReference().getDescriptor()),
          apiClass,
          AndroidApiLevel.B,
          referenceMap);
    }

    assert ensureAllPublicMethodsAreMapped(
        appView, lookupMap, methodMap, fieldMap, referenceMap, androidJar);

    try (FileOutputStream fileOutputStream = new FileOutputStream(pathToApiLevels.toFile())) {
      DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
      generateDatabase(referenceMap, dataOutputStream);
    }
  }

  private static boolean ensureAllPublicMethodsAreMapped(
      AppView<AppInfoWithClassHierarchy> appView,
      Map<ClassReference, ParsedApiClass> lookupMap,
      Map<ClassReference, Map<DexMethod, AndroidApiLevel>> methodMap,
      Map<ClassReference, Map<DexField, AndroidApiLevel>> fieldMap,
      Map<DexReference, AndroidApiLevel> referenceMap,
      Path androidJar) {
    Map<DexType, String> missingMemberInformation = new IdentityHashMap<>();
    for (DexLibraryClass clazz : appView.app().asDirect().libraryClasses()) {
      ParsedApiClass parsedApiClass = lookupMap.get(clazz.getClassReference());
      if (parsedApiClass == null) {
        if (clazz.isPublic()) {
          missingMemberInformation.put(clazz.getType(), "Could not be found in " + androidJar);
        }
        continue;
      }
      StringBuilder classBuilder = new StringBuilder();
      Map<DexField, AndroidApiLevel> fieldMapForClass = fieldMap.get(clazz.getClassReference());
      assert fieldMapForClass != null;
      clazz.forEachClassField(
          field -> {
            if (field.getAccessFlags().isPublic()
                && referenceMap.get(field.getReference()) == null
                && !field.toSourceString().contains("this$0")) {
              classBuilder.append("  ").append(field).append(" is missing\n");
            }
          });
      Map<DexMethod, AndroidApiLevel> methodMapForClass = methodMap.get(clazz.getClassReference());
      assert methodMapForClass != null;
      clazz.forEachClassMethod(
          method -> {
            if (method.getAccessFlags().isPublic()
                && referenceMap.get(method.getReference()) == null
                && !appView.dexItemFactory().objectMembers.isObjectMember(method.getReference())) {
              classBuilder.append("  ").append(method).append(" is missing\n");
            }
          });
      if (classBuilder.length() > 0) {
        missingMemberInformation.put(clazz.getType(), classBuilder.toString());
      }
    }

    // api-versions.xml do not encode all members of StringBuffers and StringBuilders, check that we
    // only have missing definitions for those two classes.
    assert missingMemberInformation.size() == 7;
    assert missingMemberInformation.containsKey(appView.dexItemFactory().stringBufferType);
    assert missingMemberInformation.containsKey(appView.dexItemFactory().stringBuilderType);
    // TODO(b/231126636): api-versions.xml has missing definitions for the below classes.
    assert missingMemberInformation.containsKey(
        appView.dexItemFactory().createType("Ljava/util/concurrent/ConcurrentHashMap$KeySetView;"));
    assert missingMemberInformation.containsKey(
        appView.dexItemFactory().createType("Ljava/time/chrono/ThaiBuddhistDate;"));
    assert missingMemberInformation.containsKey(
        appView.dexItemFactory().createType("Ljava/time/chrono/HijrahDate;"));
    assert missingMemberInformation.containsKey(
        appView.dexItemFactory().createType("Ljava/time/chrono/JapaneseDate;"));
    assert missingMemberInformation.containsKey(
        appView.dexItemFactory().createType("Ljava/time/chrono/MinguoDate;"));
    return true;
  }

  private static class ConstantPool {

    private final IntBox intBox = new IntBox(0);
    private final Map<DexString, Integer> pool = new LinkedHashMap<>();

    public int getOrAdd(DexString string) {
      return pool.computeIfAbsent(string, ignored -> intBox.getAndIncrement());
    }

    public void forEach(ThrowingBiConsumer<DexString, Integer, IOException> consumer)
        throws IOException {
      for (Entry<DexString, Integer> entry : pool.entrySet()) {
        consumer.accept(entry.getKey(), entry.getValue());
      }
    }

    public int size() {
      return pool.size();
    }
  }

  private static int setUniqueConstantPoolEntry(int id) {
    return setBitAtIndex(id, 32);
  }

  public static void generateDatabase(
      Map<DexReference, AndroidApiLevel> referenceMap, DataOutputStream outputStream)
      throws Exception {
    Map<Integer, List<Pair<DexReference, AndroidApiLevel>>> generationMap = new HashMap<>();
    ConstantPool constantPool = new ConstantPool();

    int constantPoolHashMapSize = 1 << AndroidApiDataAccess.entrySizeInBitsForConstantPoolMap();
    int apiHashMapSize = 1 << AndroidApiDataAccess.entrySizeInBitsForApiLevelMap();

    for (Entry<DexReference, AndroidApiLevel> entry : referenceMap.entrySet()) {
      int newCode = AndroidApiDataAccess.apiLevelHash(entry.getKey());
      assert newCode >= 0 && newCode <= apiHashMapSize;
      generationMap
          .computeIfAbsent(newCode, ignoreKey(ArrayList::new))
          .add(Pair.create(entry.getKey(), entry.getValue()));
    }

    Set<String> uniqueHashes = new HashSet<>();
    Map<Integer, Pair<Integer, Integer>> offsetMap = new HashMap<>();
    ByteArrayOutputStream payload = new ByteArrayOutputStream();

    // Serialize api map into payload. This will also generate the entire needed constant pool.
    for (Entry<Integer, List<Pair<DexReference, AndroidApiLevel>>> entry :
        generationMap.entrySet()) {
      int startingOffset = payload.size();
      int length = serializeIntoPayload(entry.getValue(), payload, constantPool, uniqueHashes);
      offsetMap.put(entry.getKey(), Pair.create(startingOffset, length));
    }

    // Write constant pool size <u4:size>.
    outputStream.writeInt(constantPool.size());

    // Write constant pool consisting of <u4:payload_offset><u2:length>.
    assertEquals(AndroidApiDataAccess.constantPoolOffset(), outputStream.size());
    IntBox lastReadIndex = new IntBox(-1);
    constantPool.forEach(
        (string, id) -> {
          assert id > lastReadIndex.getAndIncrement();
          outputStream.writeInt(payload.size());
          outputStream.writeShort(string.content.length);
          payload.write(string.content);
        });

    // Serialize hash lookup table for constant pool.
    Map<Integer, List<Integer>> constantPoolLookupTable = new HashMap<>();
    constantPool.forEach(
        (string, id) -> {
          int constantPoolHash = constantPoolHash(string);
          assert constantPoolHash >= 0 && constantPoolHash <= constantPoolHashMapSize;
          constantPoolLookupTable
              .computeIfAbsent(constantPoolHash, ignoreKey(ArrayList::new))
              .add(id);
        });

    int[] constantPoolEntries = new int[constantPoolHashMapSize];
    int[] constantPoolEntryLengths = new int[constantPoolHashMapSize];
    for (Entry<Integer, List<Integer>> entry : constantPoolLookupTable.entrySet()) {
      // Tag if we have a unique value
      if (entry.getValue().size() == 1) {
        int id = entry.getValue().get(0);
        constantPoolEntries[entry.getKey()] = setUniqueConstantPoolEntry(id);
      } else {
        constantPoolEntries[entry.getKey()] = payload.size();
        ByteArrayOutputStream temp = new ByteArrayOutputStream();
        for (Integer id : entry.getValue()) {
          temp.write(intToShortEncodedByteArray(id));
        }
        payload.write(temp.toByteArray());
        constantPoolEntryLengths[entry.getKey()] = temp.size();
      }
    }
    // Write constant pool lookup entries consisting of <u4:payload_offset><u2:length>
    assertEquals(
        AndroidApiDataAccess.constantPoolHashMapOffset(constantPool.size()), outputStream.size());
    for (int i = 0; i < constantPoolEntries.length; i++) {
      outputStream.writeInt(constantPoolEntries[i]);
      outputStream.writeShort(constantPoolEntryLengths[i]);
    }

    int[] apiOffsets = new int[apiHashMapSize];
    int[] apiOffsetLengths = new int[apiHashMapSize];
    for (Entry<Integer, Pair<Integer, Integer>> hashIndexAndOffset : offsetMap.entrySet()) {
      assert apiOffsets[hashIndexAndOffset.getKey()] == 0;
      Pair<Integer, Integer> value = hashIndexAndOffset.getValue();
      int offset = value.getFirst();
      int length = value.getSecond();
      apiOffsets[hashIndexAndOffset.getKey()] = offset;
      apiOffsetLengths[hashIndexAndOffset.getKey()] = length;
    }

    // Write api lookup entries consisting of <u4:payload_offset><u2:length>
    assertEquals(
        AndroidApiDataAccess.apiLevelHashMapOffset(constantPool.size()), outputStream.size());
    for (int i = 0; i < apiOffsets.length; i++) {
      outputStream.writeInt(apiOffsets[i]);
      outputStream.writeShort(apiOffsetLengths[i]);
    }

    // Write the payload.
    outputStream.write(payload.toByteArray());
  }

  /** This will serialize a collection of DexReferences and apis into a byte stream. */
  private static int serializeIntoPayload(
      List<Pair<DexReference, AndroidApiLevel>> pairs,
      ByteArrayOutputStream payload,
      ConstantPool constantPool,
      Set<String> seen)
      throws IOException {
    ByteArrayOutputStream temp = new ByteArrayOutputStream();
    for (Pair<DexReference, AndroidApiLevel> pair : pairs) {
      byte[] uniqueDescriptorForReference =
          getUniqueDescriptorForReference(pair.getFirst(), constantPool::getOrAdd);
      assert uniqueDescriptorForReference != getNonExistingDescriptor();
      if (!seen.add(Arrays.toString(uniqueDescriptorForReference))) {
        throw new Unreachable("Hash is not unique");
      }
      temp.write(intToShortEncodedByteArray(uniqueDescriptorForReference.length));
      temp.write(uniqueDescriptorForReference);
      temp.write((byte) pair.getSecond().getLevel());
    }
    byte[] tempArray = temp.toByteArray();
    payload.write(tempArray);
    return tempArray.length;
  }

  public static byte[] intToShortEncodedByteArray(int value) {
    assert isU2(value);
    byte[] bytes = new byte[2];
    bytes[0] = (byte) (value >> 8);
    bytes[1] = (byte) value;
    return bytes;
  }

  private static void computeAllReferencesInHierarchy(
      Map<ClassReference, ParsedApiClass> lookupMap,
      DexItemFactory factory,
      DexType holder,
      ParsedApiClass apiClass,
      AndroidApiLevel linkLevel,
      Map<DexReference, AndroidApiLevel> additionMap) {
    if (!apiClass.getClassReference().getDescriptor().equals(factory.objectDescriptor.toString())) {
      apiClass.visitMethodReferences(
          (apiLevel, methodReferences) -> {
            methodReferences.forEach(
                methodReference -> {
                  addIfNewOrApiLevelIsLower(
                      linkLevel,
                      additionMap,
                      apiLevel,
                      factory.createMethod(methodReference).withHolder(holder, factory));
                });
          });
      apiClass.visitFieldReferences(
          (apiLevel, fieldReferences) -> {
            fieldReferences.forEach(
                fieldReference -> {
                  addIfNewOrApiLevelIsLower(
                      linkLevel,
                      additionMap,
                      apiLevel,
                      factory.createField(fieldReference).withHolder(holder, factory));
                });
          });
      apiClass.visitSuperType(
          (superType, apiLevel) -> {
            computeAllReferencesInHierarchy(
                lookupMap,
                factory,
                holder,
                lookupMap.get(superType),
                linkLevel.max(apiLevel),
                additionMap);
          });
      apiClass.visitInterface(
          (iFace, apiLevel) -> {
            computeAllReferencesInHierarchy(
                lookupMap,
                factory,
                holder,
                lookupMap.get(iFace),
                linkLevel.max(apiLevel),
                additionMap);
          });
    }
  }

  private static void addIfNewOrApiLevelIsLower(
      AndroidApiLevel linkLevel,
      Map<DexReference, AndroidApiLevel> additionMap,
      AndroidApiLevel apiLevel,
      DexReference member) {
    AndroidApiLevel currentApiLevel = apiLevel.max(linkLevel);
    AndroidApiLevel existingApiLevel = additionMap.get(member);
    if (existingApiLevel == null || currentApiLevel.isLessThanOrEqualTo(existingApiLevel)) {
      additionMap.put(member, currentApiLevel);
    }
  }
}
