#include <windows.h>
#include <stdio.h>
#include "kbsap_module.h"
#include "kbsap_decoder.h"

#ifdef _DEBUG
#define LEAK_CHECK //メモリリーク検出（しない場合はコメントアウト）
#endif
#ifdef LEAK_CHECK
#include <crtdbg.h>
#endif
//////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
static const DWORD kbsap_Version = 0x7FFFFFFF;//デバッグ時は優先度最大
#define KBSAP_VERSION_STR L"0x7FFFFFFF(Debug)"
#else
static const DWORD kbsap_Version = 8;
#define KBSAP_VERSION_STR L"0.08"
#endif

static const wchar_t kbsap_Description[] = L"SAP Decoder v" KBSAP_VERSION_STR " based on libasap 6.0.3";
static const wchar_t kbsap_Copyright[] =   L"kbsap.kpi Copyright(C) 2016-2024 Kobarin\n"
                                           L"libasap Copyright (C) 2010-2024 Piotr Fusik";

// {CDD2C15B-71BC-45D1-90E9-076763ADC693}
static const GUID kbsap_GUID =
{ 0xcdd2c15b, 0x71bc, 0x45d1, { 0x90, 0xe9, 0x7, 0x67, 0x63, 0xad, 0xc6, 0x93 } };

static const DWORD kbsap_MultipleInstance = KPI_MULTINST_ONE;
static const wchar_t kbsap_SupportExts[] = L".sap/.cmc/.cm3/.cmr/.cms/.dmc/.dlt/.mpt/.mpd/.rmt/.tmc/.tm8/.tm2/.fc/.atr";
static const wchar_t kbsap_MultiSongExts[] = L".sap/.cmc/.cm3/.cmr/.cms/.dmc/.dlt/.mpt/.mpd/.rmt/.tmc/.tm8/.tm2/.fc/.atr";
static const DWORD kbsap_SupportTagInfo = KPI_DECODER_MODULEINFO::TAG_TITLE|
                                          KPI_DECODER_MODULEINFO::TAG_EXTRA;
static const DWORD kbsap_SupportConfig = 0;
static void* kbsap_Reserved1 = NULL;
static void* kbsap_Reserved2 = NULL;

HINSTANCE g_hKpi = NULL;
//////////////////////////////////////////////////////////////////////////////
KbSapDecoderModule::KbSapDecoderModule(void)
    :m_ModuleInfo{
        sizeof(KPI_DECODER_MODULEINFO), //cb(=sizeof(KPI_DECODER_MODULEINFO))
        KPI_DECODER_MODULE_VERSION,     //dwModuleVersion(=KPI_DECODER_MODULE_VERSION)
        kbsap_Version,
        kbsap_MultipleInstance,
        kbsap_GUID,
        kbsap_Description,
        kbsap_Copyright,
        kbsap_SupportExts,
        kbsap_MultiSongExts,
        kbsap_Reserved1,
        kbsap_Reserved2,
        kbsap_SupportTagInfo,
        kbsap_SupportConfig,
        0, 0, 0, 0                   //reserved
     }
{
}
//////////////////////////////////////////////////////////////////////////////
KbSapDecoderModule::~KbSapDecoderModule(void)
{
}
//////////////////////////////////////////////////////////////////////////////
void  WINAPI KbSapDecoderModule::GetModuleInfo(const KPI_DECODER_MODULEINFO **ppInfo)
{
    *ppInfo = &m_ModuleInfo;
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbSapDecoderModule::Open(const KPI_MEDIAINFO *cpRequest,
                                      IKpiFile     *pFile,   //音楽データ
                                      IKpiFolder   *pFolder, //音楽データがあるフォルダ
                                      IKpiDecoder **ppDecoder)
{
    KbSapDecoder *pDecoder = new KbSapDecoder;
    DWORD dwCount = pDecoder->Open(cpRequest, pFile, pFolder);
    if(dwCount == 0){
        *ppDecoder = NULL;
        delete pDecoder;
        return 0;
    }
    *ppDecoder = pDecoder;
    return dwCount;
}
/////////////////////////////////////////////////////////////////////////////
BOOL  WINAPI KbSapDecoderModule::EnumConfig(IKpiConfigEnumerator *pEnumerator)
{
    return false;
}
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbSapDecoderModule::ApplyConfig(const wchar_t *cszSection,//セクション名
                             const wchar_t *cszKey,    //キー名
                             INT64  nValue, //変更後の値(BOOL/INT の場合)
                             double dValue, //変更後の値(FLOAT の場合)
                             const wchar_t *cszValue)////変更後の値(文字列)
{
    return false;
}
/////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI kpi_CreateInstance(REFIID riid, void **ppvObject, IKpiUnknown *pUnknown)
{
    *ppvObject = NULL;
    if(!IsEqualIID(riid, IID_IKpiDecoderModule)){
        return E_NOINTERFACE;
    }
    //IKpiConfig *pConfig;
    //kpi_CreateConfig(pUnknown, &kbsap_GUID, NULL, &pConfig);
    IKpiDecoderModule *pDecoderModule = new KbSapDecoderModule;
    *ppvObject = pDecoderModule;
    //pConfig->Release();
    return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:{
        g_hKpi = hModule;
#ifdef LEAK_CHECK
        //メモリリーク検出
        int tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
        //tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
        tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
        //tmpDbgFlag |= _CRTDBG_CHECK_ALWAYS_DF;
        _CrtSetDbgFlag(tmpDbgFlag);
#endif
        DisableThreadLibraryCalls(hModule);
        break;
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
