#include <windows.h>

#ifdef _DEBUG
#define LEAK_CHECK //メモリリーク検出（しない場合はコメントアウト）
#endif
#ifdef LEAK_CHECK
#include <crtdbg.h>
#endif

#include "kbmov_module.h"
#include "kbdshow_player.h"
#include "kbmf_player.h"
#include "kbmov_config.h"

///////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
static const DWORD kbmov_Version = 0x7FFFFFFF; //デバッグ時は優先度最大
#define KBMOV_VERSION_STR L"0x7FFFFFFF(Debug)"
#else
static const DWORD kbmov_Version = 8;
#define KBMOV_VERSION_STR L"0.08"
#endif
// {90263843-F557-4EAC-8655-C423F21D68A3}
static const GUID kbmov_GUID = 
{ 0x90263843, 0xf557, 0x4eac, { 0x86, 0x55, 0xc4, 0x23, 0xf2, 0x1d, 0x68, 0xa3 } };

static const wchar_t kbmov_Description[] = L"General Movie Player v" KBMOV_VERSION_STR;
static const wchar_t kbmov_Copyright[] = L"Copyright(C) 2016-2021 Kobarin";
static const DWORD kbmov_MultipleInstance = KPI_MULTINST_INFINITE;
static const DWORD kbmov_SupportTagInfo = 0;
static const DWORD kbmov_SupportConfig = 1;

static const wchar_t kbmov_SupportExts[] = L"";//SUPPORTEXT_DEFAULT;
static const wchar_t kbmov_MultiSongExts[] = L"";
static void* kbmov_Reserved1 = NULL;
static void* kbmov_Reserved2 = NULL;

///////////////////////////////////////////////////////////////////////////////
KbMovPlayerModule::KbMovPlayerModule(IKpiConfig *pConfig)
    :m_ModuleInfo{
        sizeof(KPI_PLAYER_MODULEINFO),
        KPI_PLAYER_MODULE_VERSION,
        kbmov_Version,
        kbmov_MultipleInstance,
        kbmov_GUID,
        kbmov_Description,
        kbmov_Copyright,
        kbmov_SupportExts,
        kbmov_MultiSongExts,
        kbmov_Reserved1,
        kbmov_Reserved2,
        kbmov_SupportTagInfo,
        kbmov_SupportConfig,
        0,0,0,0}
{
    m_pszSupportExts = NULL;
    m_pConfig = pConfig;
    pConfig->AddRef();
}
///////////////////////////////////////////////////////////////////////////////
KbMovPlayerModule::~KbMovPlayerModule(void)
{
    free(m_pszSupportExts);
    m_pConfig->Release();
    KbMFPlayer::Uninitialize();
}
///////////////////////////////////////////////////////////////////////////////
void WINAPI KbMovPlayerModule::GetModuleInfo(const KPI_PLAYER_MODULEINFO **ppInfo)
{
    bool bTestMode;
    free(m_pszSupportExts);
    m_pszSupportExts = kbmov_GetSupportExts(m_pConfig, &bTestMode);
    m_ModuleInfo.cszSupportExts = m_pszSupportExts;
    m_ModuleInfo.dwPluginVersion = bTestMode ? 0x7FFFFFFF : kbmov_Version;
    *ppInfo = &m_ModuleInfo;
}
///////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbMovPlayerModule::Open(const KPI_MEDIAINFO* cpRequest,
    IKpiFile* pFile,
    IKpiFolder* pFolder,
    IKpiPlayer** ppPlayer)
{
    wchar_t szFileName[MAX_PATH];
    pFile->GetFileName(szFileName, sizeof(szFileName));
    wchar_t* pszExt = wcsrchr(szFileName, L'.');
    if (!pszExt)return 0;

    DWORD dwCount = 0;
    bool bSupportDS;
    bool bSupportMF;
    int  nPriorDS_MF;
    kbmov_IsSupport(m_pConfig, pszExt, &bSupportDS, &bSupportMF, &nPriorDS_MF);
    if(bSupportMF && bSupportDS){//拡張子両対応
        if(nPriorDS_MF == 0){//MF=>DS
            KbMFPlayer* pMFPlayer = new KbMFPlayer;
            if ((dwCount = pMFPlayer->Open(m_pConfig, pFile, pFolder)) != 0) {
                *ppPlayer = pMFPlayer;
                return dwCount;
            }
            delete pMFPlayer;
            pFile->Seek(0, FILE_BEGIN);
            KbDShowPlayer* pDShowPlayer = new KbDShowPlayer;
            if ((dwCount = pDShowPlayer->Open(m_pConfig, pFile, pFolder)) != 0) {
                *ppPlayer = pDShowPlayer;
                return dwCount;
            }
            delete pDShowPlayer;
            return 0;
        }
        else  if(nPriorDS_MF == 1) {//DS=>MF
            KbDShowPlayer* pDShowPlayer = new KbDShowPlayer;
            if ((dwCount = pDShowPlayer->Open(m_pConfig, pFile, pFolder)) != 0) {
                *ppPlayer = pDShowPlayer;
                return dwCount;
            }
            delete pDShowPlayer;
            pFile->Seek(0, FILE_BEGIN);
            KbMFPlayer* pMFPlayer = new KbMFPlayer;
            if ((dwCount = pMFPlayer->Open(m_pConfig, pFile, pFolder)) != 0) {
                *ppPlayer = pMFPlayer;
                return dwCount;
            }
            delete pMFPlayer;
            return 0;
        }
    }
    if (bSupportMF) {
        KbMFPlayer* pMFPlayer = new KbMFPlayer;
        if ((dwCount = pMFPlayer->Open(m_pConfig, pFile, pFolder)) != 0) {
            *ppPlayer = pMFPlayer;
            return dwCount;
        }
        delete pMFPlayer;
        pFile->Seek(0, FILE_BEGIN);
    }
    if (bSupportDS) {
        KbDShowPlayer* pDShowPlayer = new KbDShowPlayer;
        if ((dwCount = pDShowPlayer->Open(m_pConfig, pFile, pFolder)) != 0) {
            *ppPlayer = pDShowPlayer;
            return dwCount;
        }
        delete pDShowPlayer;
    }
    return 0;
}
///////////////////////////////////////////////////////////////////////////////
BOOL  WINAPI KbMovPlayerModule::EnumConfig(IKpiConfigEnumerator *pEnumerator)
{
    return kbmov_EnumConfig(m_pConfig, pEnumerator);
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbMovPlayerModule::ApplyConfig(const wchar_t *cszSection, //セクション名
                                            const wchar_t *cszKey,     //キー名
                                            INT64 nValue,
                                            double dValue,
                                            const wchar_t *cszValue)     
{
    return kbmov_ApplyConfig(m_pConfig, cszSection, cszKey, nValue, dValue, cszValue);
}
///////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI kpi_CreateInstance(REFIID riid, void **ppvObject, IKpiUnknown *pUnknown)
{
    *ppvObject = NULL;
    if(!IsEqualIID(riid, IID_IKpiPlayerModule)){
        return E_NOINTERFACE;
    }
    IKpiConfig *pConfig = NULL;
    kpi_CreateConfig(pUnknown, &kbmov_GUID, NULL, &pConfig);
    IKpiPlayerModule *pPlayerModule = new KbMovPlayerModule(pConfig);
    *ppvObject = pPlayerModule;
    pConfig->Release();//KbMovPlayerModule 内で AddRef しているので必ず必要
    return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
//DllMain
/////////////////////////////////////////////////////////////////////////////
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH: {
        DisableThreadLibraryCalls(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
        break;
    }
    case DLL_PROCESS_DETACH: {
        break;
    }
    }
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
