#pragma once
#include <Windows.h>
#include <algorithm>
#include <vmprofiler.hpp>

#include "parser.h"

#define NT_HEADER( x )                                                                                                 \
    reinterpret_cast< PIMAGE_NT_HEADERS64 >( reinterpret_cast< PIMAGE_DOS_HEADER >( x )->e_lfanew + x )

namespace vm
{
    struct base_data_t
    {
        std::uintptr_t module_base;
        std::uintptr_t image_base;
    };

    struct vinstr_data
    {
        std::uint8_t vm_handler;
        std::uint64_t operand;
        std::uint8_t imm_size; // size in bits...
    };

    struct vlabel_data
    {
        std::string label_name;
        std::vector< vinstr_data > vinstrs;
    };

    struct compiled_label_data
    {
        std::string label_name;
        std::uintptr_t alloc_rva, enc_alloc_rva;
        std::vector< std::uint8_t > vinstrs;
    };

    class compiler_t
    {
      public:
        explicit compiler_t( vm::ctx_t *vmctx );
        std::vector< vlabel_data > *encode();
        std::vector< compiled_label_data > encrypt();

      private:
        std::uint64_t encrypt_rva( std::uint64_t rva );

        vm::ctx_t *vmctx;
        transform::map_t calc_jmp_transforms;
        std::vector< vlabel_data > virt_labels;
        std::vector< zydis_decoded_instr_t > encrypt_vinstrs_rva;
    };
} // namespace vm