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

#ifdef TEST_MULTIPLE
//ファイル名が空白のときは１つ目と同じデータを開く
static const wchar_t test_mid[] = {L""};
#endif

KbGuru2SMFPlayer::KbGuru2SMFPlayer(IKpiConfig *pConfig)
{
    kpi_InitMediaInfo(&m_MediaInfo);
    m_bRepeat = FALSE;
    m_dwStatus = KPI_STATUS_STOP;
    m_bDevOpen = FALSE;
    
    m_pGGS = GuruGuruSmf::Ggs4::CreateInstance();
#ifdef TEST_MULTIPLE
    m_pGGS2 = GuruGuruSmf::Ggs4::CreateInstance();
#endif
}
///////////////////////////////////////////////////////////////////////////////

KbGuru2SMFPlayer::~KbGuru2SMFPlayer(void)
{
#ifdef TEST_MULTIPLE
    if(m_pGGS2){
        m_pGGS2->FreeInstance();
    }
#endif
    if(m_pGGS) {
        if (m_bDevOpen) {
            m_pGGS->CloseDevice();    
        }
        m_pGGS->FreeInstance();
    }
}
///////////////////////////////////////////////////////////////////////////////

DWORD KbGuru2SMFPlayer::Open(IKpiFile *pFile, IKpiFolder *pFolder)
{
    if(!m_pGGS)return 0;
    // 開く
    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;
    }
    //デバイスを開くのは初回Play()時に変更
    //err = m_pGGS->OpenDevice(GuruGuruSmf::Device::DirectMusic, NULL);
    //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;
    //ループ曲なら対応してることを本体に知らせる(KPI_MEDIANFO::qwLoop にループ時間か -1 を設定する)
    //単曲リピート時にはフェードアウトしないデータを渡してくれる
    //単曲リピートが有効時にループ曲を開くと本体から 2回 Open が呼ばれるのは仕様
    //(1回目と2回目で実際は異なるデータ)
    m_MediaInfo.qwLoop = m_smfInfo.LoopTick >= 0 ? -1 : 0;
#ifdef TEST_MULTIPLE
    if(m_pGGS2){
        if(test_mid[0]){
            err = m_pGGS2->AddListFromFileW(test_mid, GuruGuruSmf::LoadOption::Buffered, 0);
        }
        else{
            err = m_pGGS2->AddListFromMemory(midiData, midiDataLength, GuruGuruSmf::LoadOption::Buffered, 0);
        }
    }
#endif
    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;
    if(!m_bDevOpen){
        err = m_pGGS->OpenDevice(GuruGuruSmf::Device::DirectMusic, NULL);
        if (err != GuruGuruSmf::GgsError::NoError) {
            return FALSE;
        }
        m_bDevOpen = TRUE;
    }
    if(dwStartPos > m_smfInfo.TotalTime){
        dwStartPos = m_smfInfo.TotalTime;
    }
    int startPos = static_cast<int>(dwStartPos * (m_smfInfo.TotalTick / (float)m_smfInfo.TotalTime));
    
    int playOptions = GuruGuruSmf::PlayOption::Exclusive;
    //非ループ曲の単曲リピートがおかしくなる曲確認(edencity.mid)
    //if(m_smfInfo.LoopTick >= 0){//ループ曲でだけリピートを有効にする
    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;
#ifdef TEST_MULTIPLE
    if(m_pGGS2){
        err = m_pGGS2->OpenDevice(GuruGuruSmf::Device::DirectMusic, NULL);
        err = m_pGGS2->Play(playOptions, 0, 0, 0, 0);
    }
#endif

    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);
}
///////////////////////////////////////////////////////////////////////////////
