#include <windows.h>
#include "kbGuru2SMF.h"
#include "kbGuru2SMF_player.h"
#include "kbGuru2SMF_config.h"


KbGuru2SMFPlayer::KbGuru2SMFPlayer(IKpiConfig *pConfig)
{
    kpi_InitMediaInfo(&m_MediaInfo);
    m_pConfig = pConfig;
    m_bRepeat = FALSE;
    m_dwStatus = KPI_STATUS_STOP;
    
    //GGSINITIALIZE();
    m_pGGS = GGS;

    pConfig->AddRef();
}
///////////////////////////////////////////////////////////////////////////////

KbGuru2SMFPlayer::~KbGuru2SMFPlayer(void)
{
    if(m_pGGS) {
        m_pGGS->ClearList();
        m_pGGS->CloseDevice();

        //GGSFREE();
        m_pGGS = NULL;
    }

    m_pConfig->Release();
}
///////////////////////////////////////////////////////////////////////////////

DWORD KbGuru2SMFPlayer::Open(IKpiFile *pFile, IKpiFolder *pFolder)
{
    // J­
    GuruGuruSmf::GGSERROR err = GuruGuruSmf::GgsError::NoError;

    LPCBYTE midiData;
    size_t midiDataLength;
    if(!pFile->GetBuffer(&midiData, &midiDataLength)) {
        return FALSE;
    }

    err = m_pGGS->AddListFromMemory(midiData, midiDataLength, GuruGuruSmf::LoadOption::Buffered, 0);
    if (err != GuruGuruSmf::GgsError::NoError) {
        return FALSE;
    }
    
    err = m_pGGS->OpenDevice(GuruGuruSmf::Device::DirectMusic, NULL);
    if(err != GuruGuruSmf::GgsError::NoError) {
        return FALSE;
    }
    /*
    err = m_pGGS->AddListFromMemory(midiData, midiDataLength, GuruGuruSmf::LoadOption::Buffered, 0);
    if(err != GuruGuruSmf::GgsError::NoError) {
        return FALSE;
    }
    */

    err = m_pGGS->GetSmfInformation(&m_smfInfo, 0);
    if(err != GuruGuruSmf::GgsError::NoError) {
        return FALSE;
    }
    
    m_MediaInfo.qwLength = (UINT64)m_smfInfo.TotalTime * 10000;
    m_MediaInfo.dwCount = 1;
    m_MediaInfo.dwNumber = 1;
    m_MediaInfo.dwFormatType = KPI_MEDIAINFO::FORMAT_PLAYER;

    return TRUE;
}
///////////////////////////////////////////////////////////////////////////////

DWORD WINAPI KbGuru2SMFPlayer::Select(DWORD dwNumber, 
                                const KPI_MEDIAINFO ** ppMediaInfo,
                                      IKpiTagInfo * pTagInfo,
                                      DWORD dwTagGetFlags)
{
    if(ppMediaInfo){
        *ppMediaInfo = NULL;
    }
    if(dwNumber > m_MediaInfo.dwCount){
        return 0;
    }
    if(!ppMediaInfo){
        return 1;
    }

    *ppMediaInfo = &m_MediaInfo;

    return 1;
}
///////////////////////////////////////////////////////////////////////////////

void WINAPI KbGuru2SMFPlayer::SetRepeat(BOOL bRepeat)
{
    m_bRepeat = bRepeat;

}
///////////////////////////////////////////////////////////////////////////////

DWORD WINAPI KbGuru2SMFPlayer::GetPosition(void)
{
    GuruGuruSmf::PlayerStatus stat;
    m_pGGS->GetPlayerStatus(&stat);

    return stat.Time;
}
///////////////////////////////////////////////////////////////////////////////

BOOL WINAPI KbGuru2SMFPlayer::Play(DWORD dwStartPos, BOOL bVisible)
{
    this->Stop();

    // ΔΆ
    GuruGuruSmf::GGSERROR err = GuruGuruSmf::GgsError::NoError;

    int startPos = static_cast<int>(dwStartPos * (m_smfInfo.TotalTick / (float)m_smfInfo.TotalTime));

    int playOptions = GuruGuruSmf::PlayOption::Exclusive;
    if(m_bRepeat) { playOptions |= GuruGuruSmf::PlayOption::Loop; } 

    err = m_pGGS->Play(playOptions, 0, startPos, 0, 0);
    if(!err) { return FALSE; }

    m_dwStatus = KPI_STATUS_PLAYING;

    return TRUE;
}
///////////////////////////////////////////////////////////////////////////////

BOOL WINAPI KbGuru2SMFPlayer::Pause(void)
{
    m_pGGS->Pause();

    return TRUE;
}
///////////////////////////////////////////////////////////////////////////////

BOOL WINAPI KbGuru2SMFPlayer::Restart(void)
{
    if(this->GetStatus() == KPI_STATUS_PAUSE) {
        m_pGGS->Restart();
    }

    return TRUE;
}
///////////////////////////////////////////////////////////////////////////////

void WINAPI KbGuru2SMFPlayer::Stop(void)
{
    m_pGGS->Stop(0);
    m_dwStatus = KPI_STATUS_STOP;
}
///////////////////////////////////////////////////////////////////////////////

DWORD WINAPI KbGuru2SMFPlayer::GetStatus(void)
{
    GuruGuruSmf::PlayerStatus stat;
    m_pGGS->GetPlayerStatus(&stat);

    switch(stat.State) {
    case GuruGuruSmf::PLAYERSTATE::Play:
        m_dwStatus = KPI_STATUS_PLAYING; break;
    case GuruGuruSmf::PLAYERSTATE::Pause:
        m_dwStatus = KPI_STATUS_PAUSE; break;
    default:
        m_dwStatus = KPI_STATUS_STOP; break;
    }

    return m_dwStatus;
}
///////////////////////////////////////////////////////////////////////////////

void WINAPI KbGuru2SMFPlayer::SetTempo(int Tempo)
{
    // TempΝ 50 ` 100 ` 200
    // SetMasterTempo() Ν 0.1 ` 1.0 ` 8.0
    float t = Tempo / 100.0f;

    m_pGGS->SetMasterTempo(t);
}
///////////////////////////////////////////////////////////////////////////////

void WINAPI KbGuru2SMFPlayer::SetVolume(int Volume)
{
    // Volume Ν 0 ` 100
    // SetMasterVolume() Ν -127 ` 0
    int vol = static_cast<int>((Volume - 100) * (127 / 100.0f));

    m_pGGS->SetMasterVolume(vol);
}
///////////////////////////////////////////////////////////////////////////////
