import {Il2cppHacker} from "./Il2cppHacker";
import {Il2cppMetadataUsageObj} from "../struct/Il2cppMetadataUsageObj";
import {Il2cppGenericInstObj} from "../struct/Il2cppGenericInstObj";


let nativeFunMap = new Map();
export var Il2cppBridgeApi = {
    nativeFunNotExistMap: new Map(),





    il2cpp_usage_obj_get_usage(medataUsage){
        let getusage = this.load("_ZN14MetadataParser26il2cpp_usage_obj_get_usageEP22IL2CppMetadataUsageObj","uint32",['pointer']);
        return getusage(medataUsage);
    },
    il2cpp_usage_obj_get_obj(medataUsage){
        let il2cpp_usage_obj_get_obj = this.load("_ZN14MetadataParser24il2cpp_usage_obj_get_objEP22IL2CppMetadataUsageObj","pointer",['pointer']);
        return il2cpp_usage_obj_get_obj(medataUsage);
    },
    il2cpp_usage_obj_get_addr(medataUsage){
        let addr = this.load("_ZN14MetadataParser25il2cpp_usage_obj_get_addrEP22IL2CppMetadataUsageObj","uint64",['pointer']);
        return addr(medataUsage);
    },
    il2cpp_usage_obj_get_metadataUsageIndex(medataUsage){
        let metadataIndex = this.load("_ZN14MetadataParser39il2cpp_usage_obj_get_metadataUsageIndexEP22IL2CppMetadataUsageObj","uint32",['pointer']);
        return metadataIndex(medataUsage);
    },
    il2cpp_usage_obj_get_stringLiteralIndex(medataUsage){
        let il2cpp_usage_obj_get_stringLiteralIndex = this.load("_ZN14MetadataParser39il2cpp_usage_obj_get_stringLiteralIndexEP22IL2CppMetadataUsageObj","uint32",['pointer']);
        return il2cpp_usage_obj_get_stringLiteralIndex(medataUsage);
    },
    il2cpp_usage_obj_get_stringLiteral(medataUsage){
        let il2cpp_usage_obj_get_stringLiteral = this.load("_ZN14MetadataParser34il2cpp_usage_obj_get_stringLiteralEP22IL2CppMetadataUsageObj","pointer",['pointer']);
        return il2cpp_usage_obj_get_stringLiteral(medataUsage);
    },
    getIl2cppConstantOffset(addr){
        let getIl2cppConstantOffset = this.load("_ZN14MetadataParser23getIl2cppConstantOffsetEm","uint64",['uint64']);
        return getIl2cppConstantOffset(addr);
    },

    getStringLiteralCount(){
        let getStringLiteralCount = this.load("_ZN14MetadataParser21getStringLiteralCountEv","uint",[]);
        return getStringLiteralCount();
    },
    getStringLiteralObjFromIndex(index){
        let getStringLiteralObjFromIndex = this.load("_ZN14MetadataParser28getStringLiteralObjFromIndexEj","pointer",['uint32']);
        return new Il2cppMetadataUsageObj(getStringLiteralObjFromIndex(index));
    },
    setGetTypeInfoFromTypeIndexAddr(addr){
        let setGetTypeInfoFromTypeIndexAddr = this.load("_ZN14MetadataParser31setGetTypeInfoFromTypeIndexAddrEm","void",['uint64']);
        return setGetTypeInfoFromTypeIndexAddr(addr);
    },
    getIl2CppMetadataRegistrationTypeCount(){
        let getIl2CppMetadataRegistrationTypeCount = this.load("_ZN14MetadataParser38getIl2CppMetadataRegistrationTypeCountEv","uint",[]);
        return getIl2CppMetadataRegistrationTypeCount();
    },
    getIl2CppMetadataTypeInfoFromIndex(index){
        let getIl2CppMetadataTypeInfoFromIndex = this.load("_ZN14MetadataParser34getIl2CppMetadataTypeInfoFromIndexEj","pointer",['uint32']);
        return new  Il2cppMetadataUsageObj(getIl2CppMetadataTypeInfoFromIndex(index));
    },
    getIl2CppTypeInfoFromIndex(index){
        let getIl2CppTypeInfoFromIndex = this.load("_ZN14MetadataParser26getIl2CppTypeInfoFromIndexEj","pointer",['uint32']);
        return new  Il2cppMetadataUsageObj(getIl2CppTypeInfoFromIndex(index));
    },
    getFieldRefsCount(){
        let getFieldRefsCount = this.load("_ZN14MetadataParser17getFieldRefsCountEv","uint",[]);
        return getFieldRefsCount();
    },
    getFieldInfoObjFromIndex(index){
        let getFieldInfoObjFromIndex = this.load("_ZN14MetadataParser24getFieldInfoObjFromIndexEj","pointer",['uint32']);
        return new  Il2cppMetadataUsageObj(getFieldInfoObjFromIndex(index));
    },
    getIl2cppGenericInstObjCount(){
        let getIl2cppGenericInstObjCount = this.load("_ZN14MetadataParser28getIl2cppGenericInstObjCountEv","int32",[]);
        return getIl2cppGenericInstObjCount();
    },
    getIl2cppGenericInstObjFromIndex(index){
        let getIl2cppGenericInstObjFromIndex = this.load("_ZN14MetadataParser32getIl2cppGenericInstObjFromIndexEj","pointer",['uint32']);
        return new  Il2cppGenericInstObj(getIl2cppGenericInstObjFromIndex(index));
    },
    il2cpp_genericInst_obj_get_method_addr(obj){
        let il2cpp_genericInst_obj_get_method_addr = this.load("_ZN18Il2cppBridgeHelper38il2cpp_genericInst_obj_get_method_addrEP20Il2cppGenericInstObj","uint64",['pointer']);
        return il2cpp_genericInst_obj_get_method_addr(obj);
    },

    il2cpp_genericInst_obj_get_class_name(obj){
        let il2cpp_genericInst_obj_get_class_name = this.load("_ZN18Il2cppBridgeHelper37il2cpp_genericInst_obj_get_class_nameEP20Il2cppGenericInstObj","pointer",['pointer']);
        return il2cpp_genericInst_obj_get_class_name(obj);
    },
    il2cpp_genericInst_obj_get_class_spaze(obj){
        let il2cpp_genericInst_obj_get_class_spaze = this.load("_ZN18Il2cppBridgeHelper38il2cpp_genericInst_obj_get_class_spazeEP20Il2cppGenericInstObj","pointer",['pointer']);
        return il2cpp_genericInst_obj_get_class_spaze(obj);
    },
    il2cpp_genericInst_obj_get_method_name(obj){
        let il2cpp_genericInst_obj_get_method_name = this.load("_ZN18Il2cppBridgeHelper38il2cpp_genericInst_obj_get_method_nameEP20Il2cppGenericInstObj","pointer",['pointer']);
        return il2cpp_genericInst_obj_get_method_name(obj);
    },

    getMethodTableCount(){
        let getMethodTableCount = this.load("_ZN14MetadataParser19getMethodTableCountEv","int32",[]);
        return getMethodTableCount();
    },
    getIl2cppMethodObjFromIndex(index){
        let getIl2cppMethodObjFromIndex = this.load("_ZN14MetadataParser27getIl2cppMethodObjFromIndexEj","pointer",['uint32']);
        return new Il2cppGenericInstObj(getIl2cppMethodObjFromIndex(index));
    },
    start64(base, size) {
        let _ZN8SoDumper7start64Emm = this.load("_ZN8SoDumper7start64Emm","void",["uint64","uint64"]);
        return _ZN8SoDumper7start64Emm(base,size);
    },
    getMetadataMethodTableCount(){
        let getMetadataMethodTableCount = this.load("_ZN14MetadataParser27getMetadataMethodTableCountEv","int32",[]);
        return getMetadataMethodTableCount();
    },
    getMetadataMethodObjFromIndex(index){
        let getMetadataMethodObjFromIndex = this.load("_ZN14MetadataParser29getMetadataMethodObjFromIndexEj","pointer",['uint32']);
        return new Il2cppMetadataUsageObj(getMetadataMethodObjFromIndex(index));
    },
    startInject(il2cppHandler) {
        let _Z6injectPv = this.load("_Z6injectPv","void",['pointer']);
        return _Z6injectPv(il2cppHandler);
    },
    /**
     * 使用内存缓存加快dump速度
     * @param exportName
     * @param reType
     * @param argTypes
     * @returns {any}
     */
    load: function (exportName, reType, argTypes) {
        // new NativeFunction(Module.findExportByName(soName, "il2cpp_domain_get"), 'pointer', []);
        let cacheFun = nativeFunMap.get(exportName);
        if (cacheFun == null) {
            let isExist = this.nativeFunNotExistMap.get(exportName);
            if (isExist === -1) {
                return undefined;
            }
            let nativePointer = Il2cppHacker.getDumpModule().findExportByName(exportName);
            if (nativePointer == null) {
                this.nativeFunNotExistMap.set(exportName, -1);
                return undefined;
            } else {
                cacheFun = new NativeFunction(nativePointer, reType, argTypes);
                nativeFunMap.set(exportName, cacheFun);
            }

        }
        return nativeFunMap.get(exportName);
    },


}