#include <cstring>
#include <jni.h>
#include <pthread.h>
#include <cstdio>
#include <unistd.h>
#include <dlfcn.h>
#include <list>
#include <vector>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <fcntl.h>
#include <linux/ptrace.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <dlfcn.h>
#include <sys/system_properties.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <KittyMemory/KittyScanner.h>
#include <KittyMemory/KittyUtils.h>
#include <pthread.h>
#include <unistd.h>
#include "KittyMemory/KittyMemory.h"
#include "KittyMemory/MemoryPatch.h"
using namespace KittyMemory;
#include "oxorany/oxorany.h"
#include "Includes/obfuscate.h"
#include "Includes/Logger.h"
#include "Includes/Macros.h"
#include "Includes/Utils.h"
#include "xdl/xdl.h"
#include "curl/json.hpp"
#include "KhanhMods/fake_dlfcn.h"
#include "KhanhMods/Call_Me.h"
#include "Struct/Class.h"
#include "Struct/Unity.h"
#include "Misc.h"
#include "zygisk.hpp"
#include "Hook.h"
#include "Jni_Stuff.h"
#define ALPHA    ( ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_Float | ImGuiColorEditFlags_NoDragDrop | ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_NoBorder )
#define NO_ALPHA ( ImGuiColorEditFlags_NoTooltip    | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_Float | ImGuiColorEditFlags_NoDragDrop | ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_NoBorder )
#include "ConstructMenu.h"
#include "Includes/hide.h"
// Hex Auto 
#define FALSE64BIT "00 00 80 D2 C0 03 5F D6"
#define TRUE64BIT  "20 00 80 D2 C0 03 5F D6"
#define RETURN64BIT "C0 03 5F D6"
#define KLYUIM(assembly, namespaceName, className, methodName, paramCount, newFunc, oldFunc) \
DobbyHook((void*)Il2CppGetMethodOffset(OBFUSCATE(assembly), OBFUSCATE(namespaceName), OBFUSCATE(className), OBFUSCATE(methodName), paramCount), (void*)newFunc, (void**)&oldFunc)

bool (*_MPMatch)(void* _this);
bool MPMatch(void* _this) {
    if (func_ghost) {
        return false;
    }
    return _MPMatch(_this);
}
void patchLib(const char* libName, uintptr_t offset, const char* hex) {
ProcMap lib;
do {
lib = KittyMemory::getLibraryBaseMap(libName);
sleep(1);
} while (!lib.isValid());
MemoryPatch::createWithHex(lib, offset, hex).Modify();
}

bool (*ResetGuest)(void* _this);
bool _ResetGuest(void* _this) {
    if (Guest) {
        return true;
    }
    return ResetGuest(_this);
}
bool (*_ShowWeaponSkin)(void* _this);
bool ShowWeaponSkin(void* _this) {
        return true;
}
bool (*_ShowWeaponSkin1)(void* _this);
bool ShowWeaponSkin1(void* _this) {
        return false;
}
void (*_RET)(void *instance);
void RET(void *instance) {
    return;
}
bool (*_False)(void *Player);
bool False(void *Player) {
return false;
}
int (*_GetSystemPhysicalMemory)(void*_this, int value);
int GetSystemPhysicalMemory(void*_this, int value) {
return (int) 10000;
}
int (*_GetPhysXState)(void*_this, int value);
int GetPhysXState(void*_this, int value){
if (_this != NULL) {
		if(FlyBR) {
            return valueBr;
    }
  return _GetPhysXState(_this, value);
}
}
int (*_EPhysXState)(void*_this, int value);
int EPhysXState(void*_this, int value){
if (_this != NULL) {
		if(FlyBR1) {
            return valueBr1;
    }
  return _EPhysXState(_this, value);
}
}
bool (*orig_IsPoseFallingHigh)(void *Player);
bool hook_IsPoseFallingHigh(void *Player){
return true;
}

ProcMap _Libil2cpp, _Libunity;
void *hack_thread(void *arg){
        while (!_Libil2cpp.isValid() || !_Libunity.isValid()) {
        _Libil2cpp = KittyMemory::getLibraryBaseMap("libil2cpp.so");
        _Libunity = KittyMemory::getLibraryBaseMap("libunity.so");
        sleep(1);
   }
   Il2CppAttach();

DobbyHook((void *) DobbySymbolResolver(OBFUSCATE("/system/lib/libEGL.so"), OBFUSCATE("eglSwapBuffers")), (void *) _eglSwapBuffers1, (void **) &orig_eglSwapBuffers1);
DobbyHook((void *) DobbySymbolResolver(OBFUSCATE("/system/lib/libandroid.so"), OBFUSCATE("ANativeWindow_getWidth")), (void *) _ANativeWindow_getWidth, (void **) &orig_ANativeWindow_getWidth);
DobbyHook((void *) DobbySymbolResolver(OBFUSCATE("/system/lib/libandroid.so"), OBFUSCATE("ANativeWindow_getHeight")), (void *) _ANativeWindow_getHeight, (void **) &orig_ANativeWindow_getHeight);
DobbyHook((void *) DobbySymbolResolver(OBFUSCATE("/system/lib/libandroid.so"), OBFUSCATE("AConfiguration_getDensity")), (void *) _AConfiguration_getDensity, (void **) &orig_AConfiguration_getDensity);
// KLEL-YUIM
KLYUIM("Assembly-CSharp.dll", "COW", "GameConfig", "get_ResetGuest", 0, _ResetGuest, ResetGuest);
KLYUIM("UnityEngine.dll", "UnityEngine", "Input", "GetTouch", 1, GetTouch, old_GetTouch);

KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "ShowWeaponSkin", 0, ShowWeaponSkin, _ShowWeaponSkin);
KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "IsWeaponSkinABStatusA", 0, ShowWeaponSkin1, _ShowWeaponSkin1);
KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "NeedWeaponSkinFireSound", 0, ShowWeaponSkin1, _ShowWeaponSkin1);
KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "UpdateBehavior", 2, _LateUpdate, LateUpdate);
KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "UpdateBehavior", 2, _LateUpdateSilent, LateUpdateSilent);
// Fly Hack
KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "IsIgnoreHighFalling", 0, hook_IsPoseFallingHigh, orig_IsPoseFallingHigh);
KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "get_IsPoseFallingHigh", 0, hook_IsPoseFallingHigh, orig_IsPoseFallingHigh);
KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "OnStopCatapultFalling", 0, hook_IsPoseFallingHigh, orig_IsPoseFallingHigh);
KLYUIM("Assembly-CSharp.dll", "", "PhysXData", "get_IsJumpPadFalling", 0, hook_IsPoseFallingHigh, orig_IsPoseFallingHigh);
KLYUIM("Assembly-CSharp.dll", "", "PhysXData", "get_IsSkateboardJumping", 0, hook_IsPoseFallingHigh, orig_IsPoseFallingHigh);
KLYUIM("Assembly-CSharp.dll", "", "PhysXData", "get_IsSlideFalling", 0, hook_IsPoseFallingHigh, orig_IsPoseFallingHigh);
KLYUIM("Assembly-CSharp.dll", "COW.GamePlay", "Player", "GetPhysXState", 0, GetPhysXState, _GetPhysXState);
/*
MemoryPatch::createWithHex((uintptr_t)Il2CppGetMethodOffset(OBFUSCATE("Assembly-CSharp.dll"), OBFUSCATE("GCommon"), OBFUSCATE("PlatformUtility"), OBFUSCATE("GetSystemPhysicalMemory"), 0), OBFUSCATE(FALSE64BIT)).Modify();
MemoryPatch::createWithHex((uintptr_t)Il2CppGetMethodOffset(OBFUSCATE("Assembly-CSharp.dll"), OBFUSCATE("proto"), OBFUSCATE("AndroidApplicationToDetectDesc"), OBFUSCATE(".ctor"), 0), OBFUSCATE(FALSE64BIT)).Modify();
// Fix crash
MemoryPatch::createWithHex((uintptr_t)Il2CppGetMethodOffset(OBFUSCATE("Assembly-CSharp.dll"), OBFUSCATE("AnoSDKNamespace"), OBFUSCATE("IOPOOHPNCKH"), OBFUSCATE("DPLMGOJKKCM"), 1), OBFUSCATE("C0 03 5F D6")).Modify();
MemoryPatch::createWithHex((uintptr_t)Il2CppGetMethodOffset(OBFUSCATE("Assembly-CSharp.dll"), OBFUSCATE("AnoSDKNamespace"), OBFUSCATE("IOPOOHPNCKH"), OBFUSCATE("ADHAMOJAEBB"), 1), OBFUSCATE("C0 03 5F D6")).Modify();
MemoryPatch::createWithHex((uintptr_t)Il2CppGetMethodOffset(OBFUSCATE("Assembly-CSharp.dll"), OBFUSCATE("AnoSDKNamespace"), OBFUSCATE("IOPOOHPNCKH"), OBFUSCATE("PNPMPDMGKHJ"), 1), OBFUSCATE("C0 03 5F D6")).Modify();
MemoryPatch::createWithHex((uintptr_t)Il2CppGetMethodOffset(OBFUSCATE("Assembly-CSharp.dll"), OBFUSCATE("AnoSDKNamespace"), OBFUSCATE("IOPOOHPNCKH"), OBFUSCATE("LJGJMOPAEFB"), 1), OBFUSCATE("C0 03 5F D6")).Modify();
*/
Pathghost = MemoryPatch::createWithHex(((uintptr_t)Il2CppGetMethodOffset(OBFUSCATE("Assembly-CSharp.dll"), OBFUSCATE("COW.GamePlay"), OBFUSCATE("MPMatch") , OBFUSCATE("NeedSendMessage"), 1)) ,"00 00 80 D2 C0 03 5F D6");

DobbyHook((void *)PhimSetNhatban(0x4994188), (void *)EPhysXState, (void **)&_EPhysXState);

   return nullptr;
}
__attribute__((constructor))
void lib_main() {

}
REGISTER_ZYGISK_MODULE(MyModule)
REGISTER_ZYGISK_COMPANION(companion_handler)

extern "C" {
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
        jvm = vm;
        JNIEnv *env;
        if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
            return JNI_FALSE;
        }
        pthread_t ptid;
        pthread_create(&ptid, nullptr, hack_thread, nullptr);
        return JNI_VERSION_1_6;
    }
}
