
#pragma once

#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <dlfcn.h>
#include <vector>

#include "imgui.h"
#include "imgui_impl_android.h"
#include "imgui_impl_opengl3.h"
#include "main.h"
#include "Struct/tools.hpp"
#include <Struct/ESP.h>
//#include <Struct/Hook.h>
//#include "Icon/Font.h"

inline static bool g_IsSetup = false;
inline int prevWidth, prevHeight;


int (*o_inject_event)(JNIEnv *env, jobject thiz, jobject inputEvent);
int hook_input(JNIEnv *env, jobject __this, jobject input_event) {
    ImGuiIO &io = ImGui::GetIO();
    
    jclass motionEventClass = env->FindClass(OBFUSCATE("android/view/MotionEvent"));
    
    if (env->IsInstanceOf(input_event, motionEventClass)) {
        jmethodID getActionMethod = env->GetMethodID(motionEventClass, OBFUSCATE("getAction"), OBFUSCATE("()I"));
        jint getAction = env->CallIntMethod(input_event, getActionMethod);
        
        jmethodID getXMethod = env->GetMethodID(motionEventClass, OBFUSCATE("getX"), OBFUSCATE("()F"));
        jfloat getX = env->CallFloatMethod(input_event, getXMethod);
        
        jmethodID getYMethod = env->GetMethodID(motionEventClass, OBFUSCATE("getY"), OBFUSCATE("()F"));
        jfloat getY = env->CallFloatMethod(input_event, getYMethod);
        
        jmethodID getPointerCountMethod = env->GetMethodID(motionEventClass, OBFUSCATE("getPointerCount"), OBFUSCATE("()I"));
        jint getPointerCount = env->CallIntMethod(input_event, getPointerCountMethod);
        
        switch(getAction) {
            
        case 0:
            io.MouseDown[0] = true;
            break;
        case 1:
            io.MouseDown[0] = false;
            break;
        case 2:
            if (getPointerCount > 1) {
                io.MouseDown[0] = false;
            } else {
                io.MouseWheel = 0;
            }
            break;
        }
        io.MousePos = ImVec2(getX, getY);
    }
    
    jclass KeyEventClass = env->FindClass(OBFUSCATE("android/view/KeyEvent"));
    if (env->IsInstanceOf(input_event, KeyEventClass)) {
        jmethodID getActionMethod = env->GetMethodID(KeyEventClass, OBFUSCATE("getAction"), OBFUSCATE("()I"));
        if (env->CallIntMethod(input_event, getActionMethod) == 0) {
            jmethodID getKeyCodeMethod = env->GetMethodID(KeyEventClass, OBFUSCATE("getKeyCode"), OBFUSCATE("()I"));
            jmethodID getUnicodeCharMethod = env->GetMethodID(KeyEventClass, OBFUSCATE("getUnicodeChar"), OBFUSCATE("(I)I"));
            jmethodID getMetaStateMethod = env->GetMethodID(KeyEventClass, OBFUSCATE("getMetaState"), OBFUSCATE("()I"));
            
            jint keyCode = env->CallIntMethod(input_event, getKeyCodeMethod);
            switch (keyCode)
            {
                case 19:
                    io.KeysDown[io.KeyMap[ImGuiKey_UpArrow]] = true;
                    break;
                case 20:
                    io.KeysDown[io.KeyMap[ImGuiKey_DownArrow]] = true;
                    break;
                case 21:
                    io.KeysDown[io.KeyMap[ImGuiKey_LeftArrow]] = true;
                    break;
                case 22:
                    io.KeysDown[io.KeyMap[ImGuiKey_RightArrow]] = true;
                    break;
                case 66:
                    io.KeysDown[io.KeyMap[ImGuiKey_Enter]] = true;
                    break;
                case 67:
                    io.KeysDown[io.KeyMap[ImGuiKey_Backspace]] = true;;
                    break;
                case 111:
                    io.KeysDown[io.KeyMap[ImGuiKey_Escape]] = true;
                    break;
                case 112:
                    io.KeysDown[io.KeyMap[ImGuiKey_Delete]] = true;
                    break;
                case 122:
                    io.KeysDown[io.KeyMap[ImGuiKey_Home]] = true;
                    break;
                case 123:
                    io.KeysDown[io.KeyMap[ImGuiKey_End]] = true;
                    break;
                default:
                    io.AddInputCharacter(env->CallIntMethod(input_event, getUnicodeCharMethod, env->CallIntMethod(input_event, getMetaStateMethod)));
                    break;
            }
        }
    }
    return o_inject_event(env, __this, input_event);
}

void *(*orig_Input)(void *, void *, const void *);
void *Input(void *inst, void *motionEvent, const void *inputMessage) {
    void *result = orig_Input(inst, motionEvent, inputMessage);
    ImGui_ImplAndroid_HandleInputEvent((AInputEvent*) inst);
    return result;
}


int32_t (*orig_ANativeWindow_getWidth)(ANativeWindow* window);
int32_t _ANativeWindow_getWidth(ANativeWindow* window) {
	prevWidth = orig_ANativeWindow_getWidth(window);
	return orig_ANativeWindow_getWidth(window);
}

int32_t (*orig_ANativeWindow_getHeight)(ANativeWindow* window);
int32_t _ANativeWindow_getHeight(ANativeWindow* window) {
	prevHeight = orig_ANativeWindow_getHeight(window);
	return orig_ANativeWindow_getHeight(window);
}


float density = -1;

int32_t (*orig_AConfiguration_getDensity)(ANativeWindow* config);
int32_t _AConfiguration_getDensity(ANativeWindow* config) {
    density = orig_AConfiguration_getDensity(config);
    return orig_AConfiguration_getDensity(config);
}

ImFont *font;

/*

void SetupImgui() {
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();

    ImGui_ImplAndroid_Init(nullptr);
    ImGui_ImplOpenGL3_Init("#version 300 es");

    // Font config
    ImFontConfig fontCfg;
    fontCfg.FontDataOwnedByAtlas = false;
    fontCfg.SizePixels = 22.0f; // 2x text size

    static const ImWchar vietnamese_chars[] = {
        0x0020, 0x00FF, 0x0102, 0x0103, 0x0110, 0x0111,
        0x0128, 0x0129, 0x0168, 0x0169, 0x01A0, 0x01A1,
        0x01AF, 0x01B0, 0x1EA0, 0x1EF9, 0
    };
    io.Fonts->AddFontFromMemoryTTF((void*)BaiduZY_data, BaiduZY_size, 22.0f, &fontCfg, vietnamese_chars);
    io.Fonts->AddFontDefault(&fontCfg);

    // Style config
    ImGuiStyle& style = ImGui::GetStyle();
    style.WindowTitleAlign = ImVec2(0.5f, 0.5f);
    style.WindowPadding = ImVec2(8.0f, 8.0f);
    style.FramePadding = ImVec2(6.0f, 5.0f);
    style.ItemSpacing = ImVec2(8.0f, 6.0f);
    style.ScrollbarSize = 12.0f;
    style.GrabMinSize = 12.0f;
    style.FrameRounding = 5.0f;
    style.WindowRounding = 7.0f;

    ImGui::StyleColorsLight(); // base light style

    // Define a common color for title & tab background
    ImVec4 blueColor = ImVec4(0.3f, 0.45f, 0.85f, 1.0f); // matching blue

    // Title bar
    style.Colors[ImGuiCol_TitleBg]        = blueColor;
    style.Colors[ImGuiCol_TitleBgActive]  = blueColor;

    // Tab colors
    style.Colors[ImGuiCol_Tab]            = blueColor;
    style.Colors[ImGuiCol_TabHovered]     = blueColor;
    style.Colors[ImGuiCol_TabActive]      = blueColor;
    style.Colors[ImGuiCol_TabUnfocused]   = blueColor;
    style.Colors[ImGuiCol_TabUnfocusedActive] = blueColor;

    // Optional: background window color
    style.Colors[ImGuiCol_WindowBg]       = ImVec4(1.0f, 1.0f, 1.0f, 0.95f);

    // Scale entire UI
    style.ScaleAllSizes(2.0f);
}
*/


struct UnityEngine_Vector2_Fields {
    float x;
    float y;
};

struct UnityEngine_Vector2_o {
    UnityEngine_Vector2_Fields fields;
};

enum TouchPhase {
    Began = 0,
    Moved = 1,
    Stationary = 2,
    Ended = 3,
    Canceled = 4
};

struct UnityEngine_Touch_Fields {
    int32_t m_FingerId;
    struct UnityEngine_Vector2_o m_Position;
    struct UnityEngine_Vector2_o m_RawPosition;
    struct UnityEngine_Vector2_o m_PositionDelta;
    float m_TimeDelta;
    int32_t m_TapCount;
    int32_t m_Phase;
    int32_t m_Type;
    float m_Pressure;
    float m_maximumPossiblePressure;
    float m_Radius;
    float m_RadiusVariance;
    float m_AltitudeAngle;
    float m_AzimuthAngle;
};


