#include utility.js

const MamiSoundManager = function(context) {
    const probablySupported = [];
    const maybeSupported = [];
    const formats = {
        opus: 'audio/ogg;codecs=opus',
        ogg: 'audio/ogg;codecs=vorbis',
        mp3: 'audio/mpeg;codecs=mp3',
        caf: 'audio/x-caf;codecs=opus',
        wav: 'audio/wav',
    };

    (() => {
        const elem = $e('audio');
        for(const name in formats) {
            const format = formats[name];
            const support = elem.canPlayType(format);

            if(support === 'probably')
                probablySupported.push(name);
            else if(support === 'maybe')
                maybeSupported.push(name);
        }
    })();

    const extractUrl = urls => {
        if(typeof urls === 'object' && typeof urls.getSources === 'function')
            urls = urls.getSources();

        if(typeof urls === 'string')
            return urls;

        for(const type of probablySupported)
            if(type in urls && typeof urls[type] === 'string')
                return urls[type];

        for(const type of maybeSupported)
            if(type in urls && typeof urls[type] === 'string')
                return urls[type];

        throw 'No supported audio format could be determined.';
    };

    const loaded = new Map;
    context.onReset(() => loaded.clear());

    const loadBuffer = async urls => {
        const url = extractUrl(urls);

        if(loaded.has(url))
            return loaded.get(url);

        const buffer = await context.createBuffer(url);
        loaded.set(url, buffer);

        return buffer;
    };

    return {
        loadBuffer: loadBuffer,
        loadSource: async urls => context.createSource(await loadBuffer(urls)),
        unload: urls => {
            loaded.delete(extractUrl(urls));
        },
        reset: () => {
            loaded.clear();
        },
    };
};
