package com.bhikadia.receive_intent;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class IntentUtils {

    public static Bundle jsonToBundle(JSONObject json) {
        Bundle bundle = new Bundle();
        try {
            Iterator<String> iterator = json.keys();
            while (iterator.hasNext()) {
                String key = iterator.next();
                Object value = json.get(key);
                if (value instanceof String) {
                    bundle.putString(key, (String) value);
                } else if (value instanceof Integer) {
                    bundle.putInt(key, (Integer) value);
                } else if (value instanceof Long) {
                    bundle.putLong(key, (Long) value);
                } else if (value instanceof Boolean) {
                    bundle.putBoolean(key, (Boolean) value);
                } else if (value instanceof JSONObject) {
                    bundle.putBundle(key, jsonToBundle((JSONObject) value));
                } else if (value instanceof Float) {
                    bundle.putFloat(key, (Float) value);
                } else if (value instanceof Double) {
                    bundle.putDouble(key, (Double) value);
                } else {
                    bundle.putString(key, value.toString());
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return bundle;
    }

    public static Intent jsonToIntent(JSONObject json) {
        Intent intent = new Intent();
        intent.putExtras(jsonToBundle(json));
        return intent;
    }

    public static JSONObject bundleToJSON(Bundle bundle) {
        JSONObject json = new JSONObject();
        for (String key : bundle.keySet()) {
            try {
                json.put(key, wrap(bundle.get(key)));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return json;
    }

    public static Object wrap(Object o) {
        if (o == null) {
            return JSONObject.NULL;
        }
        if (o instanceof JSONArray || o instanceof JSONObject) {
            return o;
        }
        if (o == JSONObject.NULL) {
            return o;
        }
        try {
            if (o instanceof Collection<?>) {
                if (o instanceof ArrayList<?>) {
                    return toJSONArray(o);
                }
                return new JSONArray((Collection<?>) o);
            } else if (o.getClass().isArray()) {
                return toJSONArray(o);
            }
            if (o instanceof Map<?, ?>) {
                return new JSONObject((Map<?, ?>) o);
            }
            if (o instanceof Boolean || o instanceof Byte || o instanceof Character ||
                o instanceof Double || o instanceof Float || o instanceof Integer ||
                o instanceof Long || o instanceof Short || o instanceof String) {
                return o;
            }
            if (o instanceof Uri || o.getClass().getPackage().getName().startsWith("java.")) {
                return o.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static JSONArray toJSONArray(Object array) throws JSONException {
        JSONArray result = new JSONArray();
        if (!array.getClass().isArray() && !(array instanceof ArrayList<?>)) {
            throw new JSONException("Not a primitive array: " + array.getClass());
        }

        if (array instanceof List<?>) {
            for (Object item : (List<?>) array) {
                result.put(wrap(item));
            }
        } else if (array instanceof Object[]) {
            for (Object item : (Object[]) array) {
                result.put(wrap(item));
            }
        } else if (array instanceof ArrayList<?>) {
            for (Object item : (ArrayList<?>) array) {
                result.put(wrap(item));
            }
        } else {
            int length = java.lang.reflect.Array.getLength(array);
            for (int i = 0; i < length; i++) {
                result.put(wrap(java.lang.reflect.Array.get(array, i)));
            }
        }

        return result;
    }

    public static List<String> getApplicationSignature(Context context, String packageName) {
        List<String> signatureList = new ArrayList<>();
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                // New signature
                PackageManager pm = context.getPackageManager();
                var sig = pm.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES).signingInfo;
                if (sig.hasMultipleSigners()) {
                    for (var signer : sig.apkContentsSigners) {
                        MessageDigest digest = MessageDigest.getInstance("SHA-256");
                        digest.update(signer.toByteArray());
                        signatureList.add(bytesToHex(digest.digest()));
                    }
                } else {
                    for (var signer : sig.signingCertificateHistory) {
                        MessageDigest digest = MessageDigest.getInstance("SHA-256");
                        digest.update(signer.toByteArray());
                        signatureList.add(bytesToHex(digest.digest()));
                    }
                }
            } else {
                var sig = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures;
                for (var signature : sig) {
                    MessageDigest digest = MessageDigest.getInstance("SHA-256");
                    digest.update(signature.toByteArray());
                    signatureList.add(bytesToHex(digest.digest()));
                }
            }
            return signatureList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return signatureList;
    }

    public static String bytesToHex(byte[] bytes) {
        char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
}
