package android.app;

import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.GosPackageState;
import android.content.pm.SrtPermissions;
import android.ext.dcl.DynCodeLoading;
import android.location.HookedLocationManager;
import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.app.ContactScopes;
import com.android.internal.app.StorageScopesAppHooks;
import com.android.internal.gmscompat.GmsHooks;

import java.util.Objects;

class ActivityThreadHooks {

    private static volatile boolean called;

    // called after the initial app context is constructed
    // ActivityThread.handleBindApplication
    static Bundle onBind(Context appContext) {
        if (called) {
            throw new IllegalStateException("onBind called for the second time");
        }
        called = true;

        AppGlobals.setInitialPackageId(appContext.getApplicationInfo().ext().getPackageId());

        if (Process.isIsolated()) {
            return null;
        }

        final String pkgName = appContext.getPackageName();
        final String TAG = "AppBindArgs";

        Bundle args = null;
        try {
            args = ActivityThread.getPackageManager().getExtraAppBindArgs(pkgName);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }

        if (args == null) {
            Log.e(TAG, "bundle is null");
            return null;
        }

        int[] flags = Objects.requireNonNull(args.getIntArray(AppBindArgs.KEY_FLAGS_ARRAY));

        SrtPermissions.setFlags(flags[AppBindArgs.FLAGS_IDX_SPECIAL_RUNTIME_PERMISSIONS]);

        HookedLocationManager.setFlags(flags[AppBindArgs.FLAGS_IDX_HOOKED_LOCATION_MANAGER]);

        DynCodeLoading.handleAppBindFlags(flags[AppBindArgs.FLAGS_IDX_DYN_CODE_LOADING]);

        return args;
    }

    // called after ActivityThread instrumentation is inited, which happens before execution of any
    // of app's code
    // ActivityThread.handleBindApplication
    static void onBind2(Context appContext, Bundle appBindArgs) {
        GosPackageState gosPs = appBindArgs.getParcelable(AppBindArgs.KEY_GOS_PACKAGE_STATE,
                GosPackageState.class);
        onGosPackageStateChanged(appContext, gosPs, true);
    }

    // called from both main and worker threads
    static void onGosPackageStateChanged(Context ctx, GosPackageState state, boolean fromBind) {
        StorageScopesAppHooks.maybeEnable(state);
        ContactScopes.maybeEnable(ctx, state);
    }

    static Service instantiateService(String className) {
        Service res = null;
        if (res == null) {
            res = GmsHooks.maybeInstantiateService(className);
        }
        return res;
    }
}
