// Copyright (c) 2008-2010 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones
// This file is part of the "cAudio Engine"
// For conditions of distribution and use, see copyright notice in cAudio.h

#ifndef IAUDIOMANAGER_H
#define IAUDIOMANAGER_H

#include "IListener.h"
#include "cAudioDefines.h"
#include "EAudioFormats.h"
#include "IAudioEffects.h"
#include "IDataSourceFactory.h"
#include "IManagerEventHandler.h"
#include <string>

namespace cAudio
{
class IAudioSource;
class IAudioDecoderFactory;

//! Interface for the playback capabilities of cAudio.
class IAudioManager
{
public:
    IAudioManager() { }
    virtual ~IAudioManager() { }

    //! Initializes the manager.
    /**
    \param deviceName: Name of the device to create this manager for.
    \param outputFrequency: Frequency of the output audio or -1 for the device default.
    \param eaxEffectSlots: Number of EFX effect slots to request.  Has no effect if EFX is not supported or compiled out.
    \return True on success, False if initialization of OpenAL failed. */
    virtual bool initialize(const char* deviceName = 0x0, int outputFrequency = -1, int eaxEffectSlots = 4) = 0;

    //! Shuts the manager down, cleaning up audio sources in the process.  Does not clean up decoders, data sources, or event handlers.
    virtual void shutDown() = 0;

    //! If threading is disabled, you must call this function every frame to update the playback buffers of audio sources.  Otherwise it should not be called.
    virtual void update() = 0;

    //! Returns an Audio Source by its "name" and NULL if the name is not found
    /**
    \param name: Name of the audio source to retrieve.
    \return Pointer to the audio source object or NULL if it could not be found.*/
    virtual IAudioSource* getSoundByName(const char* name) = 0;

    //! Releases ALL Audio Sources (but does not shutdown the manager)
    virtual void releaseAllSources() = 0;

    //! Releases a single Audio Source, removing it from the manager.
    /** \param source: Pointer to the source to release. */
    virtual void release(IAudioSource* source) = 0;

    //! Returns the name of an available playback device.
    /** \param index: Specify which name to retrieve ( Range: 0 to getAvailableDeviceCount()-1 )
    \return Name of the selected device. */
    virtual const char* getAvailableDeviceName(unsigned int index) = 0;

    //! Returns the number of playback devices available for use.
    /** \return Number of playback devices available. */
    virtual unsigned int getAvailableDeviceCount() = 0;

    //! Returns the name of the default system playback device.
    /** \return Name of the default playback device. */
    virtual const char* getDefaultDeviceName() = 0;

    //! Creates an Audio Source object using the highest priority data source that has the referenced filename
    /**
    \param name: Name of the audio source.
    \param filename: Path to the file to load audio data from.
    \param stream: Whether to stream the audio data or load it all into a memory buffer at the start.  You should consider using streaming for really large sound files.
    \return A pointer to an Audio Source or NULL if creation failed.
    */
    virtual IAudioSource* create(const char* name, const char* filename, bool stream = false) = 0;

    //! Creates an Audio Source from a memory buffer using a specific audio codec.
    /**
    \param name: Name of the audio source.
    \param data: Pointer to a buffer in memory to load the data from.
    \param length: Length of the data buffer.
    \param extension: Extension for the audio codec of the data in the memory buffer.
    \return A pointer to an Audio Source or NULL if creation failed.
    */
    virtual IAudioSource* createFromMemory(const char* name, const char* data, size_t length, const char* extension) = 0;

    //! Creates an Audio Source from raw audio data in a memory buffer.
    /**
    \param name: Name of the audio source.
    \param data: Pointer to a buffer in memory to load the data from.
    \param length: Length of the data buffer.
    \param frequency: Frequency (or sample rate) of the audio data.
    \param format: Format of the audio data.
    \return A pointer to an Audio Source or NULL if creation failed.
    */
    virtual IAudioSource* createFromRaw(const char* name, const char* data, size_t length, unsigned int frequency, AudioFormats format) = 0;

    //! Register an Audio Decoder.
    /**
    \param factory: Pointer to the factory instance to use.
    \param extension: Extension of the audio codec to register this decoder under.  For example, .wav for a RIFF/wav decoder.
    \return True on seccess, False if registration failed. */
    virtual bool registerAudioDecoder(IAudioDecoderFactory* factory, const char* extension) = 0;

    //! Unregister a previously registered Audio Decoder.
    /** Note that all current sound sources will still continue to use any currently allocated decoders. Will NOT delete any user added factory instance, you must do that yourself.
    \param extension: Extension for the audio decoder to remove. */
    virtual void unRegisterAudioDecoder(const char* extension) = 0;

    //! Returns whether an audio decoder is currently registered for this file type
    /**
    \param extension: Extension for the audio decoder to check for.
    \return True if the specified decoder is registered or False if not. */
    virtual bool isAudioDecoderRegistered(const char* extension) = 0;

    //! Returns a registered audio decoder factory.
    /**
    \param extension: Extension for the audio decoder to return.
    \return A pointer to the found factory or NULL if it could not be found. */
    virtual IAudioDecoderFactory* getAudioDecoderFactory(const char* extension) = 0;

    //! Unregisters all attached Audio Decoders.
    /** Note that all current sound sources will still continue to use any currently allocated decoders. Will NOT delete any user added factory instance, you must do that yourself. */
    virtual void unRegisterAllAudioDecoders() = 0;

    //! Registers a data source with this manager
    /** Use this function to provide access to a custom resource manager, zip archive, vfs, or any other place you'd like to get audio files from.
    \param factory: Pointer to the data source factory to register.
    \param name: Name for the data source (ie. Zip Archive or FileSystem)
    \param priority: Determines what order data sources are asked for a file.  The higher the priority, the sooner they are asked.  cAudio stops looking for a file as soon as any data source returns it.
    \return True on success, False on failure to register. */
    virtual bool registerDataSource(IDataSourceFactory* factory, const char* name, int priority) = 0;

    //! Removes a previously registered data source.
    /** Note that sound sources will still continue to use any currently allocated sources, so you may not be able to close an open zip/archive file handle until they are done. Will NOT delete any user added factory instance, you must do that yourself.
    \param name: Name of the data source to unregister. */
    virtual void unRegisterDataSource(const char* name) = 0;

    //! Returns whether a data source is currently registered under a certain name.
    /**
    \param name: Name of the data source to check for.
    \return True if the specified data source is registered or False if not. */
    virtual bool isDataSourceRegistered(const char* name) = 0;

    //! Returns a previously registered data source factory.
    /**
    \param name: Name of the data source to return.
    \return A pointer to the found factory or NULL if it could not be found. */
    virtual IDataSourceFactory* getDataSourceFactory(const char* name) = 0;

    //! Removes all previously registered data sources.
    /** Note that sound sources will still continue to use any currently allocated sources, so you may not be able to close an open zip/archive file handle until they are done. Will NOT delete any user added factory instance, you must do that yourself. */
    virtual void unRegisterAllDataSources() = 0;

    //! Registers a new event handler with the manager.
    /**
    \param handler: Pointer to an event handler instance to register. */
    virtual void registerEventHandler(IManagerEventHandler* handler) = 0;

    //! Unregisters a previously registered event handler from the manager.
    /** Note: Will not delete your event handler, you must take care of that yourself.
    \param handler: Pointer to the event handler to remove. */
    virtual void unRegisterEventHandler(IManagerEventHandler* handler) = 0;

    //! Unregisters all previously registered event handlers from the manager.
    /** Note: Will not delete your event handler, you must take care of that yourself. */
    virtual void unRegisterAllEventHandlers() = 0;

    //! Returns the interface for the listener.
    virtual IListener* getListener() = 0;

#ifdef CAUDIO_EFX_ENABLED
    //! Returns the interface for audio effects.
    virtual IAudioEffects* getEffects() = 0;
#endif

protected:
private:
};

//! Creates an interface to an Audio Manager.
/** Note: This is the only way to get access to the audio playback capabilities of cAudio.
You must delete this interface using destroyAudioManager() once you are done with it.
\param initializeDefault: Whether to return an object initialized with the default settings.  If set to false, you must make a call to initialize before you can create audio sources.
\return A pointer to the created object, NULL if the object could not be allocated.
*/
CAUDIO_API IAudioManager* createAudioManager(bool initializeDefault = true);

//! Destroys an interface to a previously created Audio Manager and frees the memory allocated for it.
/**
\param capture: The object to destroy.
*/
CAUDIO_API void destroyAudioManager(IAudioManager* manager);

//! Returns if the thread used to update all Audio Managers is running.
/** Note: Will always return false if threading is disabled.
The library automatically shuts down the thread if no Audio Managers exist and will restart the thread on creation of a new manager.
\return True if the thread is currently running, false otherwise.
*/
CAUDIO_API bool isAudioManagerThreadRunning();
}
#endif //! IAUDIOMANAGER_H
