package org.lsposed.lspatch.loader;

import android.app.ActivityThread;
import android.app.LoadedApk;
import android.util.Log;

import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedInit;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class LSPLoader {
    private static final String TAG = "LSPatch";

    private static String describeClassLoader(ClassLoader classLoader) {
        if (classLoader == null) {
            return "null";
        }
        ClassLoader parent;
        try {
            parent = classLoader.getParent();
        } catch (Throwable t) {
            return classLoader + " parent=<error:" + t + ">";
        }
        return classLoader + " parent=" + parent;
    }

    public static void initModules(LoadedApk loadedApk) {
        var packageName = loadedApk.getPackageName();
        Log.i(TAG, "LSPLoader: initModules start loadedApk=" + loadedApk
                + " package=" + packageName
                + " resDir=" + loadedApk.getResDir()
                + " appInfo=" + loadedApk.getApplicationInfo()
                + " loadedPackagesBefore=" + XposedInit.loadedPackagesInProcess
                + " callbackCount=" + XposedBridge.sLoadedPackageCallbacks.size());
        var added = XposedInit.loadedPackagesInProcess.add(packageName);
        Log.i(TAG, "LSPLoader: add loaded package " + packageName
                + " added=" + added
                + " loadedPackagesAfter=" + XposedInit.loadedPackagesInProcess);
        XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(
                XposedBridge.sLoadedPackageCallbacks);
        lpparam.packageName = packageName;
        lpparam.processName = ActivityThread.currentProcessName();
        lpparam.classLoader = loadedApk.getClassLoader();
        lpparam.appInfo = loadedApk.getApplicationInfo();
        lpparam.isFirstApplication = true;
        Log.i(TAG, "LSPLoader: call module callbacks package=" + lpparam.packageName
                + " process=" + lpparam.processName
                + " isFirstApplication=" + lpparam.isFirstApplication
                + " classLoader=" + describeClassLoader(lpparam.classLoader)
                + " appInfo.sourceDir=" + (lpparam.appInfo == null ? null : lpparam.appInfo.sourceDir)
                + " appInfo.publicSourceDir=" + (lpparam.appInfo == null ? null : lpparam.appInfo.publicSourceDir)
                + " appInfo.dataDir=" + (lpparam.appInfo == null ? null : lpparam.appInfo.dataDir));
        XC_LoadPackage.callAll(lpparam);
        Log.i(TAG, "LSPLoader: module callbacks finished package=" + packageName);
    }
}
