package com.gantix.JailMonkey;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
import android.view.WindowManager;

import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.EventDispatcherListener;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.views.modal.ReactModalHostView;
import com.gantix.JailMonkey.EmulatorDetector.EmulatorDetector;
import com.gantix.JailMonkey.Magisk.IIsolatedService;
import com.gantix.JailMonkey.Magisk.IsolatedService;
import com.gantix.JailMonkey.SignatureCheck.SignatureCheck;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

import static android.content.Context.BIND_AUTO_CREATE;
import static com.gantix.JailMonkey.AdbEnabled.AdbEnabled.AdbEnabled;
import static com.gantix.JailMonkey.ExternalStorage.ExternalStorageCheck.isOnExternalStorage;
import static com.gantix.JailMonkey.HookDetection.HookDetectionCheck.hookDetected;
import static com.gantix.JailMonkey.Magisk.MagiskStatus.hasMagisk;
import static com.gantix.JailMonkey.MockLocation.MockLocationCheck.isMockLocationOn;
import static com.gantix.JailMonkey.Rooted.RootedCheck.isJailBroken;


public class JailMonkeyModule extends ReactContextBaseJavaModule {

    ReactApplicationContext reactContext;


    public JailMonkeyModule(ReactApplicationContext reactContext, boolean loadConstantsAsynchronously) {
        super(reactContext);

        this.reactContext = reactContext;

    }

    @Override
    public String getName() {
        return "JailMonkey";
    }


    @ReactMethod
    public void isDevelopmentSettingsMode(Promise p) {
        boolean isDevelopmentSettingsMode;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            isDevelopmentSettingsMode = Settings.System.getInt(this.reactContext.getContentResolver(), Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED, 0) != 1;
        } else {
            isDevelopmentSettingsMode = Settings.Global.getInt(this.reactContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1;
        }
        p.resolve(isDevelopmentSettingsMode);
    }


    @ReactMethod
    public void isDebuggedMode(Promise p) {
        boolean isDebuggedMode;
        if (Debug.isDebuggerConnected()) {
            isDebuggedMode = true;
        } else {
            isDebuggedMode = (this.reactContext.getApplicationContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        }
        p.resolve(isDebuggedMode);
    }


    @ReactMethod
    public void isSafe(final ReadableMap params,final Promise p) {
        final ReactContext context = getReactApplicationContext();



        boolean isRooted = false;
        String errMsg = "";

        if(params.hasKey("debug")){
            if(params.getBoolean("debug")){
                p.resolve(!isRooted);
            }
        }



        // if(isJailBroken(context)){
        //     errMsg = "isJailBroken";
        //     p.reject("rooted",errMsg);
        //     return;
        // }else if(hookDetected(context)){
        //     errMsg = "hookDetected";
        //     p.reject("rooted",errMsg);
        //     return;
        // }else if(isMockLocationOn(context)){
        //     errMsg = "isMockLocationOn";
        //     p.reject("rooted",errMsg);
        //     return;
        // }else if (isOnExternalStorage(context)){
        //     errMsg = "isOnExternalStorage";
        //     p.reject("rooted",errMsg);
        //     return;
        // }else if (AdbEnabled(context)){
        //     errMsg = "AdbEnabled";
        //     p.reject("rooted",errMsg);
        //     return;
        // }else if (Debug.isDebuggerConnected()) {
        //     errMsg = "isDebuggerConnected";
        //     p.reject("rooted",errMsg);
        //     return;
        // }
        // if(params.hasKey("keyStoreSignature")){
        //     if(!SignatureCheck.verifyAppSignature(context,params.getString("keyStoreSignature"))){
        //     errMsg = "Signature not Valid";
        //     p.reject("rooted",errMsg);
        //     return;
        //     }
        // }
        if(params.hasKey("checkEmulator")){
            if(params.getBoolean("checkEmulator")){
        EmulatorDetector.with(context)
                .setCheckTelephony(false)
                .addPackageName("com.bluestacks")
                .addPackageName("com.bignox.appcenter")
                .addPackageName("com.vphone.helper")
                .addPackageName("com.vphone.googlesign")
                .setDebug(true)
                .detect(new EmulatorDetector.OnEmulatorDetectorListener() {
                    @Override
                    public void onResult(boolean isEmulator) {
                        if(isEmulator){
                            p.reject("rooted","isEmulator");
                        }else{
                            p.resolve(true);
                        }}});
                    }else{
                        p.resolve(true);
                    }
        }else{
            p.resolve(true);
        }


    }

    static Promise staticP;
    @ReactMethod
    public void externalCheck(final ReadableMap params,final Promise p) {
        final ReactContext context = getReactApplicationContext();
        Log.i("test","externalCheck");
        if (params.hasKey("magisk")) {
            if (params.getBoolean("magisk")) {
                Log.d("magisk","running");
                if(hasMagisk){
                    p.reject("error","magisk");
                    return;
                }

            }
        }

        p.resolve(true);
    }


    @ReactMethod
    public void secureScreen(String label) {
        final ReactContext context = getReactApplicationContext();

        if(context != null && context.getCurrentActivity() != null) {
            context.getCurrentActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    context.getCurrentActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
                            WindowManager.LayoutParams.FLAG_SECURE);
                }
            });
        }
        
        ReactContext reactContext = context;
         if(reactContext != null) {
            EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
            eventDispatcher.addListener(new EventDispatcherListener() {
                @Override
                public void onEventDispatch(Event event) {
                    try {
                        if(event.getEventName().equals("topShow")){
                            if(context.getCurrentActivity() != null && context.getCurrentActivity().findViewById(event.getViewTag()) instanceof ReactModalHostView){
                                ReactModalHostView dialog = (ReactModalHostView)context.getCurrentActivity().findViewById(event.getViewTag());
                                dialog.getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
                                        WindowManager.LayoutParams.FLAG_SECURE);
                            }
                        }
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }
                }
            });
         }
        
    }


    @ReactMethod
    public void unSecureScreen() {
        final ReactContext context = getReactApplicationContext();
        context.getCurrentActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                context.getCurrentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
            }
        });
    }



    @Override
    public @Nullable
    Map<String, Object> getConstants() {
        ReactContext context = getReactApplicationContext();
        final Map<String, Object> constants = new HashMap<>();
        constants.put("isJailBroken", isJailBroken(context));
        constants.put("hookDetected", hookDetected(context));
        constants.put("canMockLocation", isMockLocationOn(context));
        constants.put("isOnExternalStorage", isOnExternalStorage(context));
        constants.put("AdbEnabled", AdbEnabled(context));
        return constants;
    }
}
