#include <sfx.h>
#include <sfx/port.h>
#include <header.h>
#include <SDL.h>
#include <SDL_mixer.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>

static bool mixer_init;

void sfx_free(struct sound *const s)
{
    if (s && s->chunk)
        Mix_FreeChunk(s->chunk);
}

int sfx_play(const struct sound *const s)
{
    if (mixer_init && Mix_PlayChannel(-1, s->chunk, s->loop ? -1 : 0) < 0)
        return -1;

    return 0;
}

static int load_data(struct sound *const s, FILE *const f)
{
    int ret = -1;
    SDL_RWops *const ops = SDL_RWFromFP(f, 0);

    if (!ops)
    {
        fprintf(stderr, "SDL_RWFromFP: %s\n", SDL_GetError());
        goto end;
    }
    else if (!(s->chunk = Mix_LoadWAV_RW(ops, 0)))
    {
        fprintf(stderr, "Mix_LoadWAV_RW: %s\n", SDL_GetError());
        goto end;
    }

    ret = 0;

end:
    SDL_FreeRW(ops);
    return ret;
}

static int load_header(struct sound *const s, FILE *const f)
{
    if (header_load_bool(f, "loop", &s->loop))
        return -1;

    return 0;
}

int sfx_sound_from_fp(struct sound *const s, FILE *const f, const size_t sz)
{
    if (mixer_init)
    {
        if (load_header(s, f) || load_data(s, f))
            return -1;
    }
    else
        /* Skip the file. */
        fseek(f, sz, SEEK_CUR);

    return 0;
}

void sfx_deinit(void)
{
    if (mixer_init)
        Mix_CloseAudio();

    if (SDL_WasInit(SDL_INIT_AUDIO) & SDL_INIT_AUDIO)
        SDL_QuitSubSystem(SDL_INIT_AUDIO);
}

int sfx_init(void)
{
    enum {CHUNK_SZ = 4096};

    /* Some older systems might not support sound at all. */
    if (SDL_InitSubSystem(SDL_INIT_AUDIO))
    {
        fprintf(stderr, "SDL_InitSubSystem: %s\n", SDL_GetError());
        goto failure;
    }

    if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY,
            MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, CHUNK_SZ))
    {
        fprintf(stderr, "Mix_OpenAudio: %s\n", SDL_GetError());
        goto failure;
    }
    else
        mixer_init = true;

    return 0;

failure:
    sfx_deinit();
    fprintf(stderr, "Running without audio support\n");
    return 0;
}
