#pragma once
#include "loader/binary.hpp"
#include <vector>
#include <string>
#include <map>

class PELoader : public Binary
{
    public:
        PELoader();
        ~PELoader() override;

        bool load(const string& path) override;
        BinaryFormat getFormat() const override { return BinaryFormat::PE; }
        Arch getArch() const override { return m_arch; }
        addr_t getEntryPoint() const override { return m_entry; }
        addr_t getImageBase() const override { return m_image_base; }
        vector<uint8_t> readBytes(addr_t vaddr, size_t size) const override;
        vector<pair<addr_t, addr_t>> getDataRanges() const override;
        vector<pair<addr_t, addr_t>> getExecutableRanges() const override;
        vector<pair<addr_t, addr_t>> getRuntimeFunctions() const override;
        vector<pair<addr_t, string>> getExportedFunctions() const override;
        vector<ImportEntry> getImportedFunctions() const override;
        const string& getPath() const override { return m_path; }

    private:
        bool parseHeaders();
        bool parseImportTable();
        bool parseExportTable();

        string m_path;
        Arch m_arch;
        addr_t m_entry;
        addr_t m_image_base;
        vector<uint8_t> m_data;
        vector<pair<addr_t, addr_t>> m_exec_ranges;
        vector<pair<addr_t, addr_t>> m_data_ranges;
        vector<pair<addr_t, addr_t>> m_pdata;
        vector<pair<addr_t, string>> m_exports;
        vector<ImportEntry> m_imports;
};
