#pragma once

// Includes
#if CC_VOX_ENABLED == 1
#include "Sound/SoundManager.h"

#else // CC_VOX_ENABLED == 0
#include <RKTypes.h>
#include <RKString.h>
#include <RKList.h>

#undef  SOUND
#define SOUND CasualCore::SoundManager::Get()

// Forward declarations
namespace vox {
  class DataHandle        {};
  class DescriptorManager {};
  class EmitterHandle     {};
  typedef float f32;
}

// Defines
enum EmitterState
{
// States
  ES_ERROR      = 0x00,
  ES_PLAYING    = 0x01,
  ES_PAUSED     = 0x02,
  ES_STOPPED    = 0x04,
// Sub-states
  ES_FADINGIN   = 0x10,
  ES_FADINGOUT  = 0x20
};

enum MusicMode
{
  EM_GAMEMUSIC,
  EM_USERMUSIC
};

#define InvalidUid                        -1
typedef int                               SoundHandle;
typedef void (*SoundStateChangedCallback) (SoundHandle& Handle, void* pUserData, EmitterState eState);

namespace CasualCore
{
  class SoundManager
  {
  public:
    SoundManager()              {}
    static SoundManager* Get()  { return &ms_instance; }

  public:

    bool        Initialize(const char* pSetupPackFileName = "setup.voxpack", const char* pMasterGroupName = "master", const char* pMusicGroupName = "music", const char* pSfxGroupName = "sfx", const char* pSnapshotFileName = "setup.vgs") { return true; }
    bool        LoadSoundData(const char* pSetupPackFileName = "setup.voxpack", const char* pMasterGroupName = "master", const char* pMusicGroupName = "music", const char* pSfxGroupName = "sfx")                { return true; }
    bool        LoadSoundSettings()                 { return true; }
    bool        SaveSoundSettings()                 { return true; }
    bool        LoadSound(const char* pLabel)       { return true; }
    bool        UnloadSound(const char* pLabel)     { return true; }
    bool        LoadGroupSnapshotConfiguration(const char* configurationFilename) { return true; }
    bool        PushGroupSnapshot(const char* name) { return true; }
    bool        PopGroupSnapshot(const char* name)  { return true; }
    void        ResetGroupSnapshot()                { }
    void        Shutdown()                          { }

    void        SetListenerPosition(float fX, float fY, float fZ) {}
    void        SetListenerOrientation(float fLookX, float fLookY, float fLookZ, float fUpX, float fUpY, float fUpZ) {}

    bool        CreateEmitter(const char* pLabel, SoundHandle& outHandle)                   { return true; }
    SoundHandle Play(const char* pLabel, float fFade = 0.0f)                                { return SoundHandle(); }
    SoundHandle Play(const char* pLabel, float fX, float fY, float fZ, float fFade = 0.0f)  { return SoundHandle(); }
    void        Play(SoundHandle& Handle, float fFade = 0.0f)                               {}
    void        Play(SoundHandle& Handle, float fX, float fY, float fZ, float fFade = 0.0f) {}
    void        Stop(SoundHandle& Handle, float fFade = 0.0f)                               {}
    void        Pause(SoundHandle& Handle, float fFade = 0.0f)                              {}
    void        Resume(SoundHandle& Handle, float fFade = 0.0f)                             {}

    void        SetVolume(SoundHandle& Handle, float fVolume, float fFade = 0.0f)           {}
    float       GetVolume(SoundHandle& Handle)                                              { return 0.f; }
    void        SetPitch(SoundHandle& Handle, float fPitch, float fFade = 0.0f)             {}
    float       GetPitch(SoundHandle& Handle)                                               { return 0.f; }
    bool        IsPlaying(SoundHandle& Handle)                                              { return false; }
    bool        IsPaused(SoundHandle& Handle)                                               { return false; }
    bool        IsReady(SoundHandle& Handle)                                                { return false; }
    bool        IsValid(SoundHandle& Handle)                                                { return false; }
    float       GetDuration(SoundHandle& Handle)                                            { return 0.f; }
    void        SetEmitterPosition(SoundHandle& Handle, float fX, float fY, float fZ)       {}
    void        SetSoundState(SoundHandle& Handle, const char* pStateName)                  {}
    float       GetPlayCursor(SoundHandle& Handle)                                          { return 0.f; }
    void        SetPlayCursor(SoundHandle& Handle, float fTime)                             {}
    float       GetTotalPlayTime(SoundHandle& Handle)                                       { return 0.f; }

    // Music
    void        SetMusicVolume(float fVolume, float fFade = 0.0f)                           {}
    float       GetMusicVolume()                                                            { return 0.f; }

    // Sfx
    void        SetSfxVolume(float fVolume, float fFade = 0.0f)                             {}
    float       GetSfxVolume()                                                              { return 0.f; }

    // Groups
    int32       GetGroupUid(const char* pGroupName)                                         { return InvalidUid; }
    bool        GetGroupName(int32 iUid, char* pOutGroupName, uint32 iLen)                  { return false; }
    void        PlayGroup(const char* pGroupName, float fFade = 0.0f)                       {}
    void        StopGroup(const char* pGroupName, float fFade = 0.0f)                       {}
    void        PauseGroup(const char* pGroupName, float fFade = 0.0f)                      {}
    void        ResumeGroup(const char* pGroupName, float fFade = 0.0f)                     {}
    void        SetGroupVolume(int32 iGroupUid, float fVolume, float fFade = 0.0f)          {}
    float       GetGroupVolume(int32 iGroupUid)                                             { return 0.f; }
    void        SetGroupVolume(const char* pGroupName, float fVolume, float fFade = 0.0f)   {}
    float       GetGroupVolume(const char* pGroupName)                                      { return 0.f; }
    void        SetGroupPitch(int32 iGroupUid, float fPitch, float fFade = 0.0f)            {}
    float       GetGroupPitch(int32 iGroupUid)                                              { return 0.f; }
    void        SetGroupPitch(const char* pGroupName, float fPitch, float fFade = 0.0f)     {}
    float       GetGroupPitch(const char* pGroupName)                                       { return 0.f; }

    void        SetMasterVolume(float fVolume)                                              {}
    float       GetMasterVolume() const                                                     { return 0.f; }

    int32       GetEventUid(const char* pLabel)                                             { return InvalidUid; }
    int32       GetSoundUid(const char* pLabel)                                             { return InvalidUid; }
    int32       GetSoundUid(SoundHandle& Handle)                                            { return InvalidUid; }
    int32       GetGroupUid(SoundHandle& Handle)                                            { return InvalidUid; }

    void        SuspendEngine()                                                             {}
    void        ResumeEngine()                                                              {}


    // User Music
    bool        IsUserMusicPlaying()                                                        { return false; }
    void        PlayUserMusic()                                                             {}
    void        PauseUserMusic()                                                            {}
    void        EnableUserMusicNotifications(bool bEnable)                                  {}
    void        OnResumeGame();
    void        OnUserMusicStateChanged(bool bPlaying)                                      {}

    // Emitter playback state changed notifications
    void        RegisterForEmitterStateChangeNotification(SoundHandle& Handle, SoundStateChangedCallback pCallback, void* pUserData = 0) {}
    void        UnregisterForEmitterStateChangeNotification(SoundHandle& Handle)            {}

    bool        ResetEvent(const char* pLabel)                                              { return true; }

    bool        GetCustomParameter(const char* pSoundLabel, const char* pParamLabel, RKString& out)         { return false; }
    bool        GetCustomParameter(const char* pSoundLabel, const char* pParamLabel, RKList<RKString>& out) { return false; }
    bool        GetCustomParameter(const char* pSoundLabel, const char* pParamLabel, float& out)            { return false; }
    bool        GetCustomParameter(const char* pSoundLabel, const char* pParamLabel, double& out)           { return false; }
    bool        GetCustomParameter(const char* pSoundLabel, const char* pParamLabel, int& out)              { return false; }

  private:
    SoundManager(const SoundManager& other);
    SoundManager& operator=(const SoundManager& other);
    static SoundManager ms_instance;
  };
} // namespace CasualCore

#endif //CC_VOX_ENABLED == 0
