#include txtrigs.js
#include audio/context.js
#include controls/views.js
#include sound/sndmgr.js
#include sound/sndlibrary.js
#include sound/sndpacks.js

const MamiContext = function(targetBody) {
    const pub = {};

    const viewsCtx = new MamiViewsControl({ body: targetBody });
    pub.getViews = () => viewsCtx;

    let audioCtx = null;
    pub.hasAudio = function() { return audioCtx !== null; };
    pub.getAudio = function() { return audioCtx; };
    const initAudio = function() {
        if(audioCtx !== null)
            return;

        audioCtx = new MamiAudioContext;
    };
    pub.initAudio = initAudio;

    let soundMgr = null, sndPckPlay = null;
    const soundLib = new MamiSoundLibrary(),
        soundPck = new MamiSoundPacks();

    pub.initSound = function() {
        if(soundMgr !== null)
            return;

        initAudio();
        soundMgr = new MamiSoundManager(audioCtx);
        sndPckPlay = new MamiSoundPackPlayer(soundMgr, soundLib);
    };

    pub.getSound = function() { return soundMgr; };
    pub.hasSound = function() { return soundMgr !== null; };
    pub.getSoundLibrary = function() { return soundLib; };
    pub.getSoundPacks = function() { return soundPck; };
    pub.getSoundPackPlayer = function() { return sndPckPlay; };

    pub.playUrlSound = function(soundSources, complete, volume, rate) {
        if(soundMgr === null)
            return;

        const hasCallback = typeof complete === 'function';

        try {
            const soundUrl = soundMgr.findSupportedUrl(soundSources);
            if(soundUrl === null)
                return;

            const soundName = 'MamiCtx:' + soundUrl;

            if(soundMgr.isLoaded(soundName)) {
                const source = soundMgr.get(soundName);
                if(hasCallback)
                    source.whenEnded(function() {
                        complete();
                    });
                if(typeof volume === 'number')
                    source.setVolume(volume);
                if(typeof rate === 'number')
                    source.setRate(rate);
                source.play();
            } else {
                soundMgr.load(soundName, soundUrl, function(success, buffer) {
                    if(success) {
                        const source = buffer.createSource();
                        if(hasCallback)
                            source.whenEnded(function() {
                                complete();
                            });
                        if(typeof volume === 'number')
                            source.setVolume(volume);
                        if(typeof rate === 'number')
                            source.setRate(rate);
                        source.play();
                    } else {
                        console.error(buffer);
                        if(hasCallback)
                            complete();
                    }
                });
            }
        } catch(ex) {
            console.error(ex);
            if(hasCallback)
                complete();
        }
    };

    pub.playLibrarySound = function(soundName, complete, volume, rate) {
        if(soundMgr === null)
            return;

        const hasCallback = typeof complete === 'function';

        try {
            const soundInfo = soundLib.getSound(soundName);

            if(soundMgr.isLoaded(soundName)) {
                const source = soundMgr.get(soundName);
                if(hasCallback)
                    source.whenEnded(function() {
                        complete();
                    });
                if(typeof volume === 'number')
                    source.setVolume(volume);
                if(typeof rate === 'number')
                    source.setRate(rate);
                source.play();
            } else {
                soundMgr.load(soundName, soundInfo.getSources(), function(success, buffer) {
                    if(success) {
                        const source = buffer.createSource();
                        if(hasCallback)
                            source.whenEnded(function() {
                                complete();
                            });
                        if(typeof volume === 'number')
                            source.setVolume(volume);
                        if(typeof rate === 'number')
                            source.setRate(rate);
                        source.play();
                    } else {
                        console.error(buffer);
                        if(hasCallback)
                            complete();
                    }
                });
            }
        } catch(ex) {
            console.error(ex);
            if(hasCallback)
                complete();
        }
    };

    const txtTriggers =  new MamiTextTriggers;
    pub.getTextTriggers = function() { return txtTriggers; };

    let eeprom = null;
    pub.hasEEPROM = function() { return eeprom !== null };
    pub.getEEPROM = function() { return eeprom; };
    pub.createEEPROM = function(url, getToken) {
        // new EEPROM api should take a callback to get auth info instead of a string
        eeprom = new EEPROM(1, url, getToken());
    };

    return pub;
};
