#include <wasm-rt.h>
#include <client.h>

#include <iostream>

#include <AL/al.h>
#include <AL/alc.h>

#include <fugg.h>

#define TRACE_AL_CALLS 0

/* import: 'a' 'u' */
// "u": "_alSourcef",
WASM_IMPORT_IMPL(env, _alSourcef) = [](u32 a, u32 b, f32 c) {
#if TRACE_AL_CALLS
    std::cout << "_alSourcef("
              << a << ", "
              << b << ", "
              << c
              << ")" << std::endl;
#endif

    alSourcef(a, b, c);
};
// "w": "_alSourcei",
WASM_IMPORT_IMPL(env, _alSourcei) = [](u32 a, u32 b, u32 c) {
#if TRACE_AL_CALLS
    std::cout << "_alSourcei("
              << a << ", "
              << b << ", "
              << c
              << ")" << std::endl;
#endif

    alSourcei(a, b, c);
};
/* import: 'a' 'F' */
/* _alSourceStop*/
WASM_IMPORT_IMPL(env, _alSourceStop) = [](u32 a) {
#if TRACE_AL_CALLS
    std::cout << "_alSourceStop("
              << a
              << ")" << std::endl;
#endif

    alSourceStop(a);
};
// "L": "_alGetSourcei",
WASM_IMPORT_IMPL(env, _alGetSourcei) = [](u32 a, u32 b, u32 c) {
    const auto& value = fugg::ModulePointer<ALint> { c };

#if TRACE_AL_CALLS
    std::cout << "_alGetSourcei("
              << a << ", "
              << b << ", "
              << value
              << ")" << std::endl;
#endif

    alGetSourcei(a, b, value);
};
/* import: 'a' 'Q' */
// "Q": "_alDeleteSources"
WASM_IMPORT_IMPL(env, _alDeleteSources) = [](u32 a, u32 b) {
    const auto& sources = fugg::ModulePointer<const ALuint> { b };

#if TRACE_AL_CALLS
    std::cout << "_alDeleteSources("
              << a << ", "
              << sources 
              << ")" << std::endl;
#endif

    alDeleteSources(a, sources);
};
/* _alSource3f */
WASM_IMPORT_IMPL(env, _alSource3f) = [](u32 a, u32 b, f32 c, f32 d, f32 e) {
#if TRACE_AL_CALLS
    std::cout << "_alSource3f("
              << a << ", "
              << b << ", "
              << c << ", "
              << d << ", "
              << e
              << ")" << std::endl;
#endif

    alSource3f(a, b, c, d, e);
};
/* import: 'a' 'bb' */
// "bb": "_alSourcePlay",
WASM_IMPORT_IMPL(env, _alSourcePlay) = [](u32 a) {
#if TRACE_AL_CALLS
    std::cout << "_alSourcePlay("
              << a
              << ")" << std::endl;
#endif

    alSourcePlay(a);
};
/* import: 'a' 'cb' */
// "cb": "_alListenerfv",
WASM_IMPORT_IMPL(env, _alListenerfv) = [](u32 a, u32 b) {
    const auto& values = fugg::ModulePointer<const ALfloat> { b };

#if TRACE_AL_CALLS
    std::cout << "_alListenerfv("
              << a << ", "
              << values
              << ")" << std::endl;
#endif

    alListenerfv(a, values);
};
/* import: 'a' 'db' */
// "db": "_alListener3f",
WASM_IMPORT_IMPL(env, _alListener3f) = [](u32 a, f32 b, f32 c, f32 d) {
#if TRACE_AL_CALLS
    std::cout << "_alListener3f("
              << a << ", "
              << b << ", "
              << c << ", "
              << d
              << ")" << std::endl;
#endif

    alListener3f(a, b, c, d);
};
/* import: 'a' 'Sb' */
/* _alDeleteBuffers */
WASM_IMPORT_IMPL(env, _alDeleteBuffers) = [](u32 a, u32 b) {
    const auto& buffers = fugg::ModulePointer<const ALuint> { b };

#if TRACE_AL_CALLS
    std::cout << "_alDeleteBuffers("
              << a << ", "
              << buffers
              << ")" << std::endl;
#endif

    alDeleteBuffers(a, buffers);
};
/* import: 'a' 'Tb' */
/* _alBufferData */
WASM_IMPORT_IMPL(env, _alBufferData) = [](u32 a, u32 b, u32 c, u32 d, u32 e) {
    const auto& data = fugg::ModulePointer<const ALvoid> { c };

#if TRACE_AL_CALLS
    std::cout << "_alBufferData("
              << a << ", "
              << b << ", "
              << data << ", "
              << d << ", "
              << e
              << ")" << std::endl;
#endif

    alBufferData(a, b, data, d, e);
};
/* import: 'a' 'Ub' */
// "Ub": "_alGenBuffers",
WASM_IMPORT_IMPL(env, _alGenBuffers) = [](u32 a, u32 b) {
    const auto& buffers = fugg::ModulePointer<ALuint> { b };

#if TRACE_AL_CALLS
    std::cout << "_alGenBuffers("
              << a << ", "
              << buffers
              << ")" << std::endl;
#endif

    alGenBuffers(a, buffers);
};
/* import: 'a' 'Vb' */
// "Vb": "_alGetEnumValue",
WASM_IMPORT_IMPL(env, _alGetEnumValue) = [](u32 a) {
    const auto& ename = fugg::ModulePointer<const ALchar> { a };

#if TRACE_AL_CALLS
    std::cout << "_alGetEnumValue("
              << ename 
              << ")" << std::endl;
#endif

    return static_cast<u32>(
        alGetEnumValue(ename)
    );
};
/* import: 'a' 'Wb' */
// "Wb": "_alcCloseDevice",
WASM_IMPORT_IMPL(env, _alcCloseDevice) = [](u32 a) {
    // ALCdevice is not data, but an index.
    const auto& device = reinterpret_cast<ALCdevice*>(a);

#if TRACE_AL_CALLS
    std::cout << "_alcCloseDevice("
              << device 
              << ")" << std::endl;
#endif

    return static_cast<u32>(
        alcCloseDevice(device)
    );
};
/* import: 'a' 'Yb' */
// "Yb": "_alGenSources",
WASM_IMPORT_IMPL(env, _alGenSources) = [](u32 a, u32 b) {
    const auto& sources = fugg::ModulePointer<ALuint> { b };

#if TRACE_AL_CALLS
    std::cout << "_alGenSources("
              << a << ", "
              << sources
              << ")" << std::endl;
#endif

    alGenSources(a, sources);
};
/* import: 'a' 'Zb' */
// "Zb": "_alListenerf",
WASM_IMPORT_IMPL(env, _alListenerf) = [](u32 a, f32 b) {
#if TRACE_AL_CALLS
    std::cout << "_alListenerf("
              << a << ", "
              << b
              << ")" << std::endl;
#endif

    alListenerf(a, b);
};
/* import: 'a' '_b' */
// "_b": "_alcMakeContextCurrent",
WASM_IMPORT_IMPL(env, _alcMakeContextCurrent) = [](u32 a) {
    // ALCcontext is not data, but an index.
    const auto& context = reinterpret_cast<ALCcontext*>(a);

#if TRACE_AL_CALLS
    std::cout << "_alcMakeContextCurrent("
              << context 
              << ")" << std::endl;
#endif

    return static_cast<u32>(
        alcMakeContextCurrent(context)
    );
};
/* import: 'a' '$b' */
/* _alcCreateContext */
WASM_IMPORT_IMPL(env, _alcCreateContext) = [](u32 a, u32 b) {
    // ALCdevice is not data, but an index.
    const auto& device = reinterpret_cast<ALCdevice*>(a);
    const auto& attr_list = fugg::ModulePointer<const ALCint> { b };

#if TRACE_AL_CALLS
    std::cout << "_alcCreateContext("
              << device << ", "
              << attr_list
              << ")" << std::endl;
#endif

    return reinterpret_cast<u32>(
        alcCreateContext(device, attr_list)
    );
};
/* import: 'a' 'Xb' */
// "Xb": "_alcDestroyContext",
WASM_IMPORT_IMPL(env, _alcDestroyContext) = [](u32 a) {
    // ALCcontext is not data, but an index.
    const auto& context = reinterpret_cast<ALCcontext*>(a);

#if TRACE_AL_CALLS
    std::cout << "_alcDestroyContext("
              << context
              << ")" << std::endl;
#endif

    alcDestroyContext(context);
};
/* import: 'a' 'ac' */
// "ac": "_alcOpenDevice",
WASM_IMPORT_IMPL(env, _alcOpenDevice) = [](u32 a) {
    const auto& devicename = fugg::ModulePointer<const ALchar> { a };

#if TRACE_AL_CALLS
    std::cout << "_alcOpenDevice("
              << devicename 
              << ")" << std::endl;
#endif

    return reinterpret_cast<u32>(
        alcOpenDevice(devicename)
    );
};