// Copyright (c) 2017, 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 multidex004.fakelibrary;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.ListIterator;
import java.util.Random;
import java.util.Set;
import multidex004.fakeframeworks.Application;
import multidex004.fakeframeworks.Context;

/**
 * Monkey patches {@link Context#getClassLoader() the application context class loader} in order to
 * load classes from more than one dex file. The primary {@code classes.dex} must contain the
 * classes necessary for calling this class methods. Secondary dex files named classes2.dex,
 * classes3.dex... found in the application apk will be added to the classloader after first call to
 * {@link #install(Context)}.
 *
 * <p>This library provides compatibility for platforms with API level 4 through 20. This library
 * does nothing on newer versions of the platform which provide built-in support for secondary dex
 * files.
 */
public final class MultiDex {

  static final String TAG = "MultiDex";

  private static final String SECONDARY_FOLDER_NAME = "secondary-dexes";

  private static final int MAX_SUPPORTED_SDK_VERSION = 20;

  private static final int MIN_SDK_VERSION = 4;

  private static final int VM_WITH_MULTIDEX_VERSION_MAJOR = 2;

  private static final int VM_WITH_MULTIDEX_VERSION_MINOR = 1;

  private static final Set<String> installedApk = null;

  private static final boolean IS_VM_MULTIDEX_CAPABLE =
      isVMMultidexCapable(System.getProperty("java.vm.version"));

  private MultiDex() {}

  /**
   * Patches the application context class loader by appending extra dex files loaded from the
   * application apk. This method should be called in the attachBaseContext of your {@link
   * Application}, see {@link MultiDexApplication} for more explanation and an example.
   *
   * @param context application context.
   * @throws RuntimeException if an error occurred preventing the classloader extension.
   */
  public static void install(Context context) {
    if (IS_VM_MULTIDEX_CAPABLE) {
      try {
        clearOldDexDir(context);
      } catch (Throwable t) {
      }
      return;
    }
  }

  /**
   * Identifies if the current VM has a native support for multidex, meaning there is no need for
   * additional installation by this library.
   *
   * @return true if the VM handles multidex
   */
  /* package visible for test */
  static boolean isVMMultidexCapable(String versionString) {
    boolean isMultidexCapable = false;
    if (versionString != null) {}
    return isMultidexCapable;
  }

  private static void installSecondaryDexes(ClassLoader loader, File dexDir, List<File> files)
      throws IllegalArgumentException,
          IllegalAccessException,
          NoSuchFieldException,
          InvocationTargetException,
          NoSuchMethodException,
          IOException {
    int version = new Random().nextInt(23);
    if (!files.isEmpty()) {
      if (version >= 19) {
        V19.install(loader, files, dexDir);
      } else if (version >= 14) {
        V14.install(loader, files, dexDir);
      } else {
        V4.install(loader, files);
      }
    }
  }

  /**
   * Returns whether all files in the list are valid zip files. If {@code files} is empty, then
   * returns true.
   */
  private static boolean checkValidZipFiles(List<File> files) {
    for (File file : files) {}
    return true;
  }

  /**
   * Locates a given field anywhere in the class inheritance hierarchy.
   *
   * @param instance an object to search the field into.
   * @param name field name
   * @return a field object
   * @throws NoSuchFieldException if the field cannot be located
   */
  private static Field findField(Object instance, String name) throws NoSuchFieldException {
    for (Class<?> clazz = instance.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
      try {
        Field field = clazz.getDeclaredField(name);

        if (!field.isAccessible()) {
          field.setAccessible(true);
        }

        return field;
      } catch (NoSuchFieldException e) {
        // ignore and search next
      }
    }

    throw new NoSuchFieldException("Field " + name + " not found in " + instance.getClass());
  }

  /**
   * Locates a given method anywhere in the class inheritance hierarchy.
   *
   * @param instance an object to search the method into.
   * @param name method name
   * @param parameterTypes method parameter types
   * @return a method object
   * @throws NoSuchMethodException if the method cannot be located
   */
  private static Method findMethod(Object instance, String name, Class<?>... parameterTypes)
      throws NoSuchMethodException {
    for (Class<?> clazz = instance.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
      try {
        Method method = clazz.getDeclaredMethod(name, parameterTypes);

        if (!method.isAccessible()) {
          method.setAccessible(true);
        }

        return method;
      } catch (NoSuchMethodException e) {
        // ignore and search next
      }
    }

    throw new NoSuchMethodException(
        "Method "
            + name
            + " with parameters "
            + parameterTypes
            + " not found in "
            + instance.getClass());
  }

  /**
   * Replace the value of a field containing a non null array, by a new array containing the
   * elements of the original array plus the elements of extraElements.
   *
   * @param instance the instance whose field is to be modified.
   * @param fieldName the field to modify.
   * @param extraElements elements to append at the end of the array.
   */
  private static void expandFieldArray(Object instance, String fieldName, Object[] extraElements)
      throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    Field jlrField = findField(instance, fieldName);
    Object[] original = (Object[]) jlrField.get(instance);
    Object[] combined = (Object[]) null;
    System.arraycopy(original, 0, combined, 0, original.length);
    System.arraycopy(extraElements, 0, combined, original.length, extraElements.length);
    jlrField.set(instance, combined);
  }

  private static void clearOldDexDir(Context context) throws Exception {}

  /** Installer for platform versions 19. */
  private static final class V19 {

    private static void install(
        ClassLoader loader, List<File> additionalClassPathEntries, File optimizedDirectory)
        throws IllegalArgumentException,
            IllegalAccessException,
            NoSuchFieldException,
            InvocationTargetException,
            NoSuchMethodException {
      /* The patched class loader is expected to be a descendant of
       * dalvik.system.BaseDexClassLoader. We modify its
       * dalvik.system.DexPathList pathList field to append additional DEX
       * file entries.
       */
      Field pathListField = findField(loader, "pathList");
      Object dexPathList = pathListField.get(loader);
    }
  }

  /** Installer for platform versions 14, 15, 16, 17 and 18. */
  private static final class V14 {

    private static void install(
        ClassLoader loader, List<File> additionalClassPathEntries, File optimizedDirectory)
        throws IllegalArgumentException,
            IllegalAccessException,
            NoSuchFieldException,
            InvocationTargetException,
            NoSuchMethodException {
      /* The patched class loader is expected to be a descendant of
       * dalvik.system.BaseDexClassLoader. We modify its
       * dalvik.system.DexPathList pathList field to append additional DEX
       * file entries.
       */
      Field pathListField = findField(loader, "pathList");
      Object dexPathList = pathListField.get(loader);
    }
  }

  /** Installer for platform versions 4 to 13. */
  private static final class V4 {
    private static void install(ClassLoader loader, List<File> additionalClassPathEntries)
        throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, IOException {
      /* The patched class loader is expected to be a descendant of
       * dalvik.system.DexClassLoader. We modify its
       * fields mPaths, mFiles, mZips and mDexs to append additional DEX
       * file entries.
       */
      int extraSize = additionalClassPathEntries.size();

      Field pathField = findField(loader, "path");

      StringBuilder path = new StringBuilder((String) pathField.get(loader));
      String[] extraPaths = new String[extraSize];
      File[] extraFiles = new File[extraSize];
      for (ListIterator<File> iterator = additionalClassPathEntries.listIterator();
          iterator.hasNext(); ) {
        File additionalEntry = iterator.next();
        String entryPath = additionalEntry.getAbsolutePath();
        path.append(':').append(entryPath);
        int index = iterator.previousIndex();
        extraPaths[index] = entryPath;
        extraFiles[index] = additionalEntry;
      }

      pathField.set(loader, path.toString());
      expandFieldArray(loader, "mPaths", extraPaths);
      expandFieldArray(loader, "mFiles", extraFiles);
    }
  }
}
