#pragma once
#include <Utils/SysUtils/xorstr.hpp>
//
// Created by vastrakai on 6/25/2024.
//

enum class OffsetType {
    Index,
    FieldOffset,
};

// kinda aids ik stfu
#define DEFINE_INDEX_FIELD_TYPED(type, name, str, index_offset, offset_type) \
public: \
static inline type (name) = 0; \
private: \
static void name##_initializer() { \
    static bool initialized = false; \
    if (initialized) return; \
    initialized = true; \
    auto result = scanSig(hat::compile_signature<str>(), xorstr_(#name), index_offset); \
    if (!result.has_result()) return; \
    if ((offset_type) == OffsetType::Index) name = *reinterpret_cast<type*>(reinterpret_cast<uintptr_t>(result.get()) + index_offset) / 8; \
    else (name) = *reinterpret_cast<type*>(reinterpret_cast<uintptr_t>(result.get()) + index_offset); \
} \
private: \
static inline std::function<void()> name##_function = (mSigInitializers.emplace_back(name##_initializer), std::function<void()>()); \
public:


#define DEFINE_INDEX_FIELD(name, str, index_offset, offset_type) \
public: \
static inline int (name) = 0; \
private: \
static void name##_initializer() { \
    static bool initialized = false; \
    if (initialized) return; \
    initialized = true; \
    auto result = scanSig(hat::compile_signature<str>(), xorstr_(#name), index_offset); \
    if (!result.has_result()) return; \
    if ((offset_type) == OffsetType::Index) (name) = *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(result.get()) + (index_offset)) / 8; \
    else (name) = *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(result.get()) + (index_offset)); \
} \
private: \
static inline std::function<void()> name##_function = (mSigInitializers.emplace_back(name##_initializer), std::function<void()>()); \
public:

#define DEFINE_FIELD(name, offset) \
public: \
static constexpr inline int (name) = offset;

#include <future>
#include <libhat/Scanner.hpp>

class OffsetProvider {
    static hat::scan_result scanSig(hat::signature_view sig, const std::string& name, int offset = 0);

    static inline std::vector<std::function<void()>> mSigInitializers;
    static inline int mSigScanCount;
public:
    static inline bool mIsInitialized = false;
    static inline std::unordered_map<std::string, uintptr_t> mSigs;

    DEFINE_INDEX_FIELD(ClientInstance_getLocalPlayer, "48 8B ? ? ? ? ? FF 15 ? ? ? ? 8B 88 ? ? ? ? C1 E1", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(ClientInstance_getBlockSource, "48 8b 80 ? ? ? ? ff 15 ? ? ? ? 48 8b c8 48 85 c0 75 ? 48 83 c4", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(ClientInstance_getOptions, "48 8B ? ? ? ? ? FF 15 ? ? ? ? 48 8B ? 48 8B ? 48 8B ? ? ? ? ? 48 8B ? FF 15 ? ? ? ? 3C ? 75 ? 48 8B ? 48 8B ? 48 8B ? ? ? ? ? FF 15 ? ? ? ? 3C", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(ClientInstance_getScreenName, "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC ? 48 8B EA 48 8B 01 48 8D 54 24 ? 48 8B 80 ? ? ? ? FF 15 ? ? ? ? 90 48 8B 48 ? 48 8B 01 48 8B D5 48 8B 80 ? ? ? ? FF 15 ? ? ? ? 90 48 C7 44 24 ? ? ? ? ? 48 8B 7C 24 ? 33 DB 48 89 5C 24 ? BE ? ? ? ? 48 85 FF 74 ? 8B C6 F0 0F C1 47 ? 83 F8 ? 75 ? 48 8B 07 48 8B CF 48 8B 00 FF 15 ? ? ? ? 8B C6 F0 0F C1 47 ? 83 F8 ? 75 ? 48 8B 07 48 8B CF 48 8B 40 ? FF 15 ? ? ? ? 48 8B 5C 24 ? 48 C7 44 24 ? ? ? ? ? 48 85 DB 74 ? 8B C6 F0 0F C1 43 ? 83 F8 ? 75 ? 48 8B 03 48 8B CB 48 8B 00 FF 15 ? ? ? ? F0 0F C1 73 ? 83 FE ? 75 ? 48 8B 03 48 8B CB 48 8B 40 ? FF 15 ? ? ? ? 48 8B C5 48 8B 5C 24 ? 48 8B 6C 24 ? 48 8B 74 24 ? 48 83 C4 ? 5F C3 CC CC CC CC CC 48 89 5C 24 ? 48 89 6C 24", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(ClientInstance_getMouseGrabbed, "48 8B", 3, OffsetType::Index); // PLEASE CHECK AFTER IDK IF THIS IS CORRECT!!! //TODO 48 8B ? ? ? ? ? FF 15 ? ? ? ? 84 C0 75 ? 48 8B ? ? ? ? ? 48 85 ? 0F 84 ? ? ? ? 80 38 ? 0F 84 ? ? ? ? 48 8B ? ? ? ? ? 48 85 ? 74 ? F0 FF ? ? 0F 10 ? ? ? ? ? 0F 11 ? ? ? ? ? F2 0F
    DEFINE_INDEX_FIELD(ClientInstance_setDisableInput, "48 8B 80 ? ? ? ? FF 15 ? ? ? ? 48 8B 8F ? ? ? ? E8 ? ? ? ? 33 D2", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(ClientInstance_grabMouse, "48 8B 80 ? ? ? ? FF 15 ? ? ? ? 48 8B 8F ? ? ? ? E8 ? ? ? ? 33 D2", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(ClientInstance_releaseMouse, "48 8B 80 ? ? ? ? FF 15 ? ? ? ? 48 8B 8F ? ? ? ? E8 ? ? ? ? 33 D2", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(ClientInstance_mMinecraftSim, "48 8B", 3, OffsetType::FieldOffset); //TODO 48 8B 8F ? ? ? ? E8 ? ? ? ? 88 87 ? ? ? ? 48 8B 8F
    DEFINE_INDEX_FIELD(ClientInstance_mLevelRenderer, "48 8B ? ? ? ? ? 48 85 ? 74 ? 48 8B ? ? ? ? ? 48 05 ? ? ? ? C3", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(ClientInstance_mPacketSender, "48 8B 81 ? ? ? ? C3 CC CC CC CC CC CC CC CC 48 8B 89 ? ? ? ? 48 8B 01 48 8B 80 ? ? ? ? 48 FF 25 ? ? ? ? CC CC CC CC CC CC CC CC 40 53", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(ClientInstance_mGuiData, "48 8B 8F ? ? ? ? 48 89 87 ? ? ? ? 48 85 C9 74 ? 48 8B 01 BA ? ? ? ? 48 8B 00 FF 15 ? ? ? ? 48 8B 0D ? ? ? ? 48 8B 01 BA ? ? ? ? 48 8B 40 ? FF 15 ? ? ? ? 48 8B D8 48 85 C0 75 ? 48 C7 44 24 ? ? ? ? ? 4C 89 7C 24", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(MinecraftGame_playUi, "48 8B ? ? ? ? ? FF 15 ? ? ? ? 48 83 C4 ? C3 48 89 ? ? ? 48 89 ? ? ? 57 48 83 EC ? 48 8B", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(MinecraftGame_mClientInstances, "48 8B ? ? ? ? ? 48 8B ? 48 8B ? ? 80 78 19 ? 75 ? 48 8B ? 48 8B ? 80 78 19 ? 74 ? 80 79 19 ? 75 ? 80 79 20 ? 76 ? 48 8B ? 48 3B", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(MinecraftGame_mProfanityContext, "49 8B", 4, OffsetType::FieldOffset); //TODO 49 8B ? ? ? ? ? ? 49 8B ? 48 8B ? ? ? ? ? FF 15 ? ? ? ? 48 8D ? ? E8
    DEFINE_INDEX_FIELD(MinecraftGame_mMouseGrabbed, "80 B9", 2, OffsetType::FieldOffset); //TODO 80 B9 ? ? ? ? ? 0F 84 ? ? ? ? 48 8B 01 48 8B 80 ? ? ? ? FF 15 ? ? ? ? 48 85 C0
    DEFINE_INDEX_FIELD(MainView_bedrockPlatform, "48 8B ? ? ? ? ? 48 8B ? B2 ? 48 8B ? ? ? ? ? FF 15 ? ? ? ? 84 C0", 3, OffsetType::FieldOffset); //TODO : not sure
    DEFINE_INDEX_FIELD(Actor_baseTick, "48 8D 05 ?? ?? ?? ?? 48 89 01 48 8D 05 ?? ?? ?? ?? 48 89 81 88 0A 00 00 48 8B 91 E8 12 00 00", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(MinecraftSim_mGameSim, "49 8B 84 24 F0 ? ? ? 8B 58", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(MinecraftSim_mRenderSim, "48 85 C9 74 26 48 8B 01 4C 89 7C 24 30 4C 89 45 87 48 8D 55 87 48 8B 80 40 03 ? ? FF 15", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(MinecraftSim_mGameSession, "48 8B", 3, OffsetType::FieldOffset); //TODO 48 8B ? ? ? ? ? 48 85 ? 0F 84 ? ? ? ? 44 38 ? ? 0F 84 ? ? ? ? 48 8B
    DEFINE_INDEX_FIELD_TYPED(uint8_t, GameSession_mEventCallback, "48 8B ? ? 48 85 ? 74 ? 48 8B ? 48 8B ? ? FF 15 ? ? ? ? 48 8B ? ? 48 85 ? 74 ? 48 8B ? 48 8B ? ? 48 83 C4 ? 5B 48 FF ? ? ? ? ? 48 83 C4 ? 5B C3 CC CC CC CC CC CC CC CC 48 89", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD_TYPED(uint8_t, BedrockPlatformUWP_mcGame, "48 8B ? ? 48 8B ? 48 8B ? ? FF 15 ? ? ? ? 84 C0 74 ? 48 8B ? ? 48 8B ? 48 8B ? ? FF 15 ? ? ? ? 84 C0", 3, OffsetType::FieldOffset); //TODO : not sure
    DEFINE_INDEX_FIELD(bgfx_d3d12_RendererContextD3D12_m_commandQueue, "48 8B", 3, OffsetType::FieldOffset); //8 too small wtf //TODO 48 8B 89 ? ? ? ? 4C 8B 46
    DEFINE_INDEX_FIELD(bgfx_context_m_renderCtx, "48 8B ? ? ? ? ? 48 8B ? 48 8B ? ? FF 15 ? ? ? ? 48 89 ? ? ? ? ? 48 63", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(BlockLegacy_mBlockId, "44 0F", 4, OffsetType::FieldOffset); //TODO 44 0F ? ? ? ? ? ? B8 ? ? ? ? 48 8B ? 48 8B
    DEFINE_INDEX_FIELD(BlockLegacy_mayPlaceOn, "48 8B", 3, OffsetType::Index); // 1.21.51 //TODO 48 8B ? ? ? ? ? FF 15 ? ? ? ? 49 8D ? ? 0F B6 ? E8 ? ? ? ? 48 85 ? 75 ? 49 8B ? ? 48 85 ? 0F 84 ? ? ? ? 48 83 C1 ? E8 ? ? ? ? 48 85 ? 74 ? 45 0F
    DEFINE_INDEX_FIELD(Actor_mContainerManagerModel, "49 8B ? ? ? ? ? 48 89 ? ? ? 48 89 ? ? ? F0 FF ? ? 66 0F ? ? ? ? EB ? 0F 57 ? 66 0F 73 D8 ? 66 48 ? ? ? 0F 57 ? 66 0F ? ? ? ? ? ? 48 85", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(Actor_mGameMode, "49 8B 8E ? ? ? ? 45 84 FF 74 ? 84 DB", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(Actor_mSupplies, "48 8B", 3, OffsetType::FieldOffset); //TODO (2) 48 8B ? ? ? ? ? 80 BA B0 00 00 00 ? 75 ? 48 8B ? ? ? ? ? 8B 52 ? 48 8B ? 48 8B ? ? 48 FF ? ? ? ? ? 48 8D ? ? ? ? ? C3 48 89
    DEFINE_INDEX_FIELD(PlayerInventory_mContainer, "48 8B ? ? ? ? ? 8B 52 ? 48 8B ? 48 8B ? ? 48 FF ? ? ? ? ? 48 8D", 3, OffsetType::FieldOffset); //TODO : not sure
    DEFINE_INDEX_FIELD_TYPED(uint8_t, Container_getItem, "40 53 56 57 48 83 ec 40 48 8b 05 ? ? ? ?", 3, OffsetType::Index); //TODO : not sure
    DEFINE_INDEX_FIELD(LevelRenderer_mRendererPlayer, "48 8B ? ? ? ? ? F3 0F ? ? ? ? ? ? 0F AF", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(LevelRendererPlayer_mCameraPos, "f3 0f 10 8b ? ? ? ? f3 0f 5c 83 ? ? ? ? f3 0f 10 93", 4, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(LevelRendererPlayer_mFovX, "41 0F", 3, OffsetType::FieldOffset); //TODO 41 0F 10 86 ? ? ? ? 0F 11 45 ? 41 0F 10 86 ? ? ? ? 0F 11 45 ? 41 0F 10 86 ? ? ? ? 0F 11 45 ? 41 0F 10 86 ? ? ? ? 0F 11 45 ? 41 38 BE
    DEFINE_INDEX_FIELD(LevelRendererPlayer_mFovY, "89 83", 2, OffsetType::FieldOffset); //TODO 89 83 ? ? ? ? 41 8B 44 24 ? 89 83 ? ? ? ? 41 8B 44 24 ? 89 83 ? ? ? ? 41 8B 44 24 ? 89 83 ? ? ? ? 41 8B 44 24 ? 89 83 ? ? ? ? 41 8B 44 24 ? 89 83 ? ? ? ? 41 8B 44 24 ? F3 0F 10 0D
    DEFINE_INDEX_FIELD(Actor_mSwinging, "88 ? ? ? ? ? EB ? 33 ? 89", 2, OffsetType::FieldOffset); //TODO : not sure
    DEFINE_INDEX_FIELD(Actor_swing, "48 8B ? ? ? ? ? FF 15 ? ? ? ? 48 8B ? ? ? ? ? 48 8B ? 48 8B ? 48 8B ? ? FF 15 ? ? ? ? 48 8B", 3, OffsetType::Index); //TODO : not sure
    DEFINE_INDEX_FIELD(Actor_mLevel, "48 8B ? ? ? ? ? 48 89 ? ? ? F3 0F ? ? ? 4C 8B", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD(Level_getHitResult, "48 8B", 3, OffsetType::Index); //TODO 48 8B ? ? ? ? ? FF 15 ? ? ? ? 48 8B ? 49 8B ? ? 48 8B ? ? ? ? ? 49 8B ? FF 15 ? ? ? ? F3 0F
    DEFINE_INDEX_FIELD(Level_getPlayerList, "48 8B 80 ? ? ? ? FF 15 ? ? ? ? 8B 48 ? 39 8E ? ? ? ? 0F 84", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(Level_getPlayerMovementSettings, "48 8b 82 ? ? ? ? ff 15 ? ? ? ? 80 78 ? ? 0f 84", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(Level_getLevelData, "48 8B", 3, OffsetType::Index); // Also works on .40 //TODO 48 8B 80 ? ? ? ? FF 15 ? ? ? ? 33 FF 48 8D 0D
    DEFINE_INDEX_FIELD(LevelData_mTick, "48 8b", 3, OffsetType::FieldOffset); //TODO 48 8b 98 ? ? ? ? 48 8b b5
    DEFINE_INDEX_FIELD(Actor_mDestroying, "38 9f", 2, OffsetType::FieldOffset); //TODO 38 9f ? ? ? ? 74 ? 48 8b 8f ? ? ? ? 48 8b 01
    DEFINE_INDEX_FIELD_TYPED(uint8_t, UIProfanityContext_mEnabled, "80 79", 2, OffsetType::FieldOffset); //TODO 80 79 ? ? 74 ? 80 79 ? ? 74 ? 45 ? ? 75 ? 4C 8D
    //DEFINE_INDEX_FIELD(Bone_mPartModel, "8B 81 ? ? ? ? 89 82 ? ? ? ? F3 0F ? ? ? ? ? ? 0F 57", 2, OffsetType::FieldOffset); // this isn't even correct lmao
    DEFINE_INDEX_FIELD(Actor_mHurtTimeComponent, "48 8b", 3, OffsetType::FieldOffset); //TODO 48 8b 86 ? ? ? ? 48 85 c0 74 ? 66 0f 6e 00
    DEFINE_INDEX_FIELD(BlockSource_getChunk, "48 8B ? ? ? ? ? 44 89 ? ? ? FF 15 ? ? ? ? 48 83 C4", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(BlockSource_setBlock, "48 8B ? ? ? ? ? FF 15 ? ? ? ? EB ? 41 83 FF", 3, OffsetType::Index); //TODO : not sure
    DEFINE_INDEX_FIELD(LevelChunk_mSubChunks, "48 2B ? ? ? ? ? 48 8B ? 48 C1 FF ? 48 0F", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD_TYPED(uint8_t, BlockSource_mBuildHeight, "0F BF ? ? 3B C8 0F 8D ? ? ? ? 8B 0F", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD_TYPED(uint8_t, ContainerManagerModel_getContainerType, "48 8B 40 ? FF 15 ? ? ? ? 84 C0 74 ? 80 7B ? ? 74 ? B0", 3, OffsetType::Index);//8
    DEFINE_INDEX_FIELD_TYPED(uint8_t, ContainerManagerModel_getSlot, "48 8B ? ? FF 15 ? ? ? ? 0F B6 ? ? 44 89", 3, OffsetType::Index); // what the actual fcuk is wrong with me.
    DEFINE_INDEX_FIELD(Actor_mSerializedSkin, "4C 8B ? ? ? ? ? 48 8B ? 48 8B ? ? 89 44", 3, OffsetType::FieldOffset); // ? 40 55 56 41 56 48 83 EC 30 8B et 40 55 56 41 56 48 83 EC 30 8B 41 18
    //DEFINE_INDEX_FIELD(Actor_mSerializedSkin, "4C 8B B1 98 0A 00 00 48 8B F1", 3, OffsetType::FieldOffset);
    DEFINE_INDEX_FIELD_TYPED(uint8_t, BlockLegacy_getCollisionShape, "48 8B ? ? FF 15 ? ? ? ? 0F 10 ? 0F 11 ? ? ? ? ? ? F2 0F ? ? ? F2 0F", 3, OffsetType::Index);
    DEFINE_INDEX_FIELD(BlockSource_clip, "48 8B", 3, OffsetType::Index); //TODO 48 8B 80 ? ? ? ? FF 15 ? ? ? ? 90 48 8D 95 ? ? ? ? 48 8D 8D ? ? ? ? E8 ? ? ? ? 48 8B D8

    //DEFINE_INDEX_FIELD(Actor_getStatusFlag, "E8 ? ? ? ? 84 C0 75 ? 48 8B CF E8 ? ? ? ? 48 8B C8", 3, OffsetType::Index);

    DEFINE_INDEX_FIELD(ClientInstance_getInputHandler, "48 8B", 3, OffsetType::Index); //TODO 48 8B ? ? ? ? ? FF 15 ? ? ? ? 8D 7E
    DEFINE_INDEX_FIELD(ClientInputMappingFactory_mKeyboardMouseSettings, "49 8B", 3, OffsetType::FieldOffset); // TODO: replace with betta siggy //TODO 49 8B 9D ? ? ? ? 48 89 5D ? 4D 8B AD ? ? ? ? 4C 89 6D ? E9

    //DEFINE_INDEX_FIELD_TYPED(uint8_t, ClientInputHandler_mMappingFactory, "48 8B ? ? EB ? 48 8D ? ? 48 85 ? 74 ? 48 8B ? E8 ? ? ? ? 48 8B ? 48 8B ? ? ? 48 33 ? E8 ? ? ? ? 48 8B ? ? ? 48 8B ? ? ? 48 83 C4 ? 5F C3 E8 ? ? ? ? CC CC CC CC CC CC 48 89", 3, OffsetType::FieldOffset);
    DEFINE_FIELD(ClientInputHandler_mMappingFactory, 0x28);

    // TODO: Move all CLASS_FIELD declarations and hat::member_at offsets to here
    DEFINE_FIELD(ContainerScreenController_tryExit, 12);
    DEFINE_FIELD(ItemStack_reInit, 3);
    DEFINE_FIELD(MinecraftUIRenderContext_drawImage, 7);
    DEFINE_FIELD(Actor_mEntityIdentifier, 0x240);
    DEFINE_FIELD(Actor_mLocalName, 0xC08); // ithink its updated
    DEFINE_FIELD(ClientInstance_mViewMatrix, 0x388);
    DEFINE_FIELD(ClientInstance_mFovX, 0xF88);
    DEFINE_FIELD(ClientInstance_mFovY, 0xF9C);
    DEFINE_FIELD(Block_mRuntimeId, 0xC0);
    DEFINE_FIELD(Block_mLegacy, 0x78); // 1.21.51
    DEFINE_FIELD(BlockPalette_mLevel, 0x80);

    static void initialize();
    static void deinitialize();
};
