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

#include <iostream>

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

#include <fugg.h>
#include <flyff.h>

#define TRACE_AL_CALLS 0

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

    alSourcef(source, static_cast<ALenum>(param), value);
};
// "w": "_alSourcei",
WASM_IMPORT_IMPL(env, _alSourcei) = [](u32 source, u32 param, u32 value) {
#if TRACE_AL_CALLS
    std::cout << "_alSourcei("
              << source << ", "
              << param << ", "
              << value
              << ")" << std::endl;
#endif

    alSourcei(source, static_cast<ALenum>(param), static_cast<ALenum>(value));
};
/* import: 'a' 'F' */
/* _alSourceStop*/
WASM_IMPORT_IMPL(env, _alSourceStop) = [](u32 source) {
#if TRACE_AL_CALLS
    std::cout << "_alSourceStop("
              << source
              << ")" << std::endl;
#endif

    alSourceStop(source);
};
// "L": "_alGetSourcei",
WASM_IMPORT_IMPL(env, _alGetSourcei) = [](u32 source, u32 param, u32 c) {
    const auto &value = flyff::Pointer<ALint>{c};

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

    alGetSourcei(source, static_cast<ALenum>(param), static_cast<ALint *>(value));
};
/* import: 'a' 'Q' */
// "Q": "_alDeleteSources"
WASM_IMPORT_IMPL(env, _alDeleteSources) = [](u32 n, u32 b) {
    const auto &sources = flyff::Pointer<const ALuint>{b};

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

    alDeleteSources(static_cast<ALsizei>(n), static_cast<const ALuint *>(sources));
};
/* _alSource3f */
WASM_IMPORT_IMPL(env, _alSource3f) = [](u32 source, u32 param, f32 value1, f32 value2, f32 value3) {
#if TRACE_AL_CALLS
    std::cout << "_alSource3f("
              << source << ", "
              << param << ", "
              << value1 << ", "
              << value2 << ", "
              << value3
              << ")" << std::endl;
#endif

    alSource3f(source, static_cast<ALenum>(param), value1, value2, value3);
};
/* import: 'a' 'bb' */
// "bb": "_alSourcePlay",
WASM_IMPORT_IMPL(env, _alSourcePlay) = [](u32 source) {
#if TRACE_AL_CALLS
    std::cout << "_alSourcePlay("
              << source
              << ")" << std::endl;
#endif

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

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

    alListenerfv(static_cast<ALenum>(param), static_cast<const ALfloat *>(values));
};
/* import: 'a' 'db' */
// "db": "_alListener3f",
WASM_IMPORT_IMPL(env, _alListener3f) = [](u32 param, f32 value1, f32 value2, f32 value3) {
#if TRACE_AL_CALLS
    std::cout << "_alListener3f("
              << param << ", "
              << value1 << ", "
              << value2 << ", "
              << value3
              << ")" << std::endl;
#endif

    alListener3f(static_cast<ALenum>(param), value1, value2, value3);
};
/* import: 'a' 'Sb' */
/* _alDeleteBuffers */
WASM_IMPORT_IMPL(env, _alDeleteBuffers) = [](u32 n, u32 b) {
    const auto &buffers = flyff::Pointer<const ALuint>{b};

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

    alDeleteBuffers(static_cast<ALsizei>(n), static_cast<const ALuint *>(buffers));
};
/* import: 'a' 'Tb' */
/* _alBufferData */
WASM_IMPORT_IMPL(env, _alBufferData) = [](u32 buffer, u32 format, u32 c, u32 size, u32 freq) {
    const auto &data = flyff::Pointer<const ALvoid>{c};

#if TRACE_AL_CALLS
    std::cout << "_alBufferData("
              << buffer << ", "
              << format << ", "
              << data << ", "
              << size << ", "
              << freq
              << ")" << std::endl;
#endif

    alBufferData(buffer, static_cast<ALenum>(format), static_cast<const void *>(data), static_cast<ALsizei>(size),
                 static_cast<ALsizei>(freq));
};
/* import: 'a' 'Ub' */
// "Ub": "_alGenBuffers",
WASM_IMPORT_IMPL(env, _alGenBuffers) = [](u32 n, u32 b) {
    const auto &buffers = flyff::Pointer<ALuint>{b};

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

    alGenBuffers(static_cast<ALsizei>(n), static_cast<ALuint *>(buffers));
};
/* import: 'a' 'Vb' */
// "Vb": "_alGetEnumValue",
WASM_IMPORT_IMPL(env, _alGetEnumValue) = [](u32 a) {
    const auto &ename = flyff::Pointer<const ALchar>{a};

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

    return static_cast<u32>(alGetEnumValue(static_cast<const ALchar *>(ename)));
};
/* import: 'a' 'Wb' */
// "Wb": "_alcCloseDevice",
WASM_IMPORT_IMPL(env, _alcCloseDevice) = [](u32 a) {
    // ALCdevice is not data, but an id.
    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 n, u32 b) {
    const auto &sources = flyff::Pointer<ALuint>{b};

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

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

    alListenerf(static_cast<ALenum>(param), value);
};
/* import: 'a' '_b' */
// "_b": "_alcMakeContextCurrent",
WASM_IMPORT_IMPL(env, _alcMakeContextCurrent) = [](u32 a) {
    // ALCcontext is not data, but an id.
    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 id.
    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 id.
    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 = flyff::Pointer<const ALchar>{a};

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

    return reinterpret_cast<u32>(alcOpenDevice(static_cast<const ALchar *>(devicename)));
};