#pragma once
#include "utils.hpp"
#include "linker/linker.hpp"
#include "obfuscation/obfuscation.hpp"

#include <Zycore/Zycore.h>
#include <Zydis/Decoder.h>
#include <Zydis/Formatter.h>

#include <winternl.h>
#include <type_traits>
#include <dbghelp.h>
#include <mutex>
#include <string>

#pragma comment(lib, "Dbghelp.lib")
namespace theo
{
	using malloc_t = std::function<void*(std::size_t bytes, std::uint32_t prot)>;
	using memcpy_t = std::function<decltype(memcpy)>;

	using resolve_symbol_t = std::function<std::uintptr_t(const char*)>;
	using mapper_routines_t = std::tuple<malloc_t, memcpy_t, resolve_symbol_t>;

	class hmm_ctx
	{
	public:
		explicit hmm_ctx(const mapper_routines_t& routines);
		auto map_objs(std::vector<lnk::obj_buffer_t>& objs) -> bool;
		auto get_symbol(std::string symbol_name) -> std::uintptr_t;

		malloc_t alloc;
		memcpy_t mcopy;
		resolve_symbol_t resolve_symbol;
	private:
		bool map_symbols(std::vector<lnk::obj_buffer_t>& objs);
		bool map_obfuscated_symbols(std::vector<lnk::obj_buffer_t>& objs);

		bool resolve_relocs(std::vector<lnk::obj_buffer_t>& objs);
		bool alloc_obfuscated_symbol_space(std::vector<lnk::obj_buffer_t>& objs);
		bool alloc_symbol_space(std::vector<lnk::obj_buffer_t>& objs);

		std::map<std::string, std::uintptr_t> mapped_symbols;
		std::map<std::uintptr_t, std::shared_ptr<obfuscation::obfuscate>> obfuscated_gadgets;
	};
}