#include <Bass.h>
#include "SM_Music.h"
#include "SM_Main.h"



namespace SM_Music
{
IEventHandler* g_pEventHandler=0;
HMUSIC         g_hMusic       =0;
HSYNC          g_hSync        =0;
bool           g_bPlaying     =false;

HSTREAM        g_hMP3         =0;


void CALLBACK SyncProc(HSYNC handle, DWORD channel, DWORD data, DWORD user)
{
  if (g_pEventHandler)
  {
    g_pEventHandler->Notify(LOWORD(data), HIWORD(data));
  }
}

int Init(HWND hwnd)
{
  if (BASS_Init(-1, 44100, 0, hwnd)!=TRUE)
  {
    return (-1);
  }

  return (0);
}

int Shutdown()
{
  BASS_Free();
  return (0);
}

int Load(char * pcMusicBinary, int iLength)
{ 
  g_hMusic=BASS_MusicLoad(TRUE, pcMusicBinary, 0, iLength, 0/*BASS_MUSIC_LOOP*/);

  if (!g_hMusic)
  {
    return (-1);
  }

  return (0);
}

int Free()
{
  BASS_MusicFree(g_hMusic);
  return (0);
}

int Play(bool bLoop)
{
  BASS_Start();    
  if (g_bPlaying==false)
  {
    if (BASS_MusicPlayEx(g_hMusic, LOWORD(0) | HIWORD(0), bLoop?BASS_MUSIC_LOOP:0, FALSE)==FALSE)
    {
      return (-1);
    }
    g_hSync=BASS_ChannelSetSync(g_hMusic, BASS_SYNC_MUSICPOS, -1, SyncProc, 0);
    g_bPlaying=true;
  }
  return (0);
}

int PlayEx(int iPos, int iRow, bool bLoop)
{
  Stop();
  BASS_Start();    
  if (BASS_MusicPlayEx(g_hMusic, LOWORD(iPos) | HIWORD(iRow), bLoop?BASS_MUSIC_LOOP:0, FALSE)==FALSE)
  {
    return (-1);
  }

  g_hSync=BASS_ChannelSetSync(g_hMusic, BASS_SYNC_MUSICPOS, -1, SyncProc, 0);
  g_bPlaying=true;

  return (0);
}

int Pause()
{
  BASS_Pause();
  return (0);
}


int Stop()
{
  if (g_bPlaying)
  {
    BASS_Stop();
    g_bPlaying=false;
    BASS_ChannelRemoveSync(g_hMusic, g_hSync);    
  }
  
    
  return (0);
}

int SetVol(int iVolume)
{
  BASS_SetVolume(iVolume);  
  return (0);
}

int SetEventHandler(IEventHandler* pEventHandler)
{
  g_pEventHandler=pEventHandler;
  return (0);
}


int     MP3Load         (char* pcMP3  , int iLength)
{
  g_hMP3=BASS_StreamCreateFile(TRUE, pcMP3, 0, iLength, BASS_MP3_SETPOS);

  if (!g_hMP3)
  {
    return (-1);
  }
    
  return (0);
}

int     MP3Play         ()
{
  BASS_Start();        
  if (BASS_StreamPlay(g_hMP3, FALSE, 0)!=TRUE)
  {
    return (-1);
  }
  g_bPlaying=true;
  return (0);
}

int     MP3PlayEx       (float fTime)
{  
  MP3Stop();
  BASS_Start();    
  
  DWORD dwOffset,dwLength,dwFreq,dwFlags;

  dwLength=(long) BASS_StreamGetLength(g_hMP3); // length in bytes

  BASS_ChannelGetAttributes(g_hMP3, &dwFreq, 0 ,0); // sample rate
  dwFlags=BASS_ChannelGetFlags(g_hMP3); // stereo/mono, 8/16 bit flags

  dwOffset=DWORD(fTime*float((dwFreq*(dwFlags&BASS_SAMPLE_MONO?1:2)*(dwFlags&BASS_SAMPLE_8BITS?1:2))));
  BASS_ChannelSetPosition(g_hMP3, dwOffset);
  g_bPlaying=true;
  BASS_StreamPlay(g_hMP3, FALSE, 0);
    
  return (0);
}

float   MP3Time         ()
{
  DWORD dwPosition, dwFreq, dwFlags;

  dwPosition=(long) BASS_ChannelGetPosition(g_hMP3);


  //len=BASS_StreamGetLength(a_stream); // length in bytes
  BASS_ChannelGetAttributes(g_hMP3,&dwFreq,0,0); // sample rate
  dwFlags=BASS_ChannelGetFlags(g_hMP3); // stereo/mono, 8/16 bit flags
  float fTime=float(dwPosition)/float((dwFreq*(dwFlags&BASS_SAMPLE_MONO?1:2)*(dwFlags&BASS_SAMPLE_8BITS?1:2))); 

  return (fTime);
}

int     MP3Free         ()
{
  BASS_StreamFree(g_hMP3);  
  return (0);
}


int     MP3Stop         ()
{
  if (g_bPlaying)
  {
    BASS_Stop();
    g_bPlaying=false;    
  }

  return (0);
}


}