#include "fugg.h"
#include "client.h"

#include <iostream>

#include <emscripten/heap.h>
#include "interop/imports.h"

void *malloc (size_t __size) {
    using namespace fugg::interop;
    // This malloc is always called from the runtime.

    if((*import::_malloc) != nullptr) {
        // Since this malloc is always called from the interop, we need to 
        // transform it to point to the actual address where the WASM runtime memory
        // resides.

        const auto& ptr = fugg::ModulePointer<void> {
            (*import::_malloc)(__size)
        };

#if TRACE_ALLOC
        std::cout << "FLYFF: Allocated " << __size << " bytes at " << ptr << std::endl;
#endif

        return ptr;
    } else {
        auto ptr = emscripten_builtin_malloc(__size);

#if TRACE_ALLOC
        std::cout << "FUGG: Allocated " << __size << " bytes at " << ptr << std::endl;
#endif

        return ptr;
    }
}

void free (void *__ptr) {
    using namespace fugg::interop;
    // printf("Trying to free ptr %p\n", __ptr);

    if((*import::_free) != nullptr) {
        const auto& ptr = fugg::RuntimePointer<void> { __ptr };

        (*import::_free)(ptr.as_raw());

#if TRACE_ALLOC
        std::cout << "FLYFF: Free'd pointer at " << ptr << std::endl; 
#endif
    } else {
        emscripten_builtin_free(__ptr);

#if TRACE_ALLOC
        printf("FUGG: Free'd pointer at %p\n", __ptr);
#endif
    }
}

int main() {
    std::cout << "Hello world from fugg!" << std::endl;
    std::cout << "Initialising runtime... ";
    
    auto& client = fugg::Client::instance();
    client.initialise();

    std::cout << "Ok!" << std::endl;

    std::cout << "Starting Flyff..." << std::endl;
    return client.main();
}