#include <windows.h>
#include <stdio.h>
#include "kbspu_config.h"
#include "kbspu_decoder.h"

static const wchar_t SEC_GENERAL[] = L"General";
static const wchar_t KEY_PATH[] = L"PATH";
static const wchar_t KEY_VIA_RUNKPI[] = L"ViaRunkpi";
static const wchar_t KEY_CONFIG[] = L"Config";

static const BOOL VIA_RUNKPI_DEFAULT = TRUE;
static const wchar_t SZ_VIA_RUNKPI_DEFAULT[] = L"1";

extern HINSTANCE g_hKpi;
/////////////////////////////////////////////////////////////////////////////
BOOL __fastcall kbspu_EnumConfig(IKpiConfigEnumerator *pEnumerator)
{
    static const KPI_CFG_SECTION sec[] = {
        {SEC_GENERAL, L"General", L"kbspu.kpi に関する一般的な設定です。"},
        {NULL, NULL, NULL}
    };
    static const KPI_CFG_KEY key[] = {
    //   type, section, key, keydesc, default, min, max, list, listdesc, help
        {KPI_CFG_TYPE_FILE, SEC_GENERAL, KEY_PATH, L"spuEternal.dll のパス",
            L"", L"spuEternal.dll(*.dll)\t*.dll", NULL, //default/min/max
            NULL, NULL, //list/listdesc
            L"spuEternal.dll のパスを指定します。\r\n"
            L"DLL がないと SPU を再生することは出来ません。\r\n"
            },//help
        {KPI_CFG_TYPE_BOOL, SEC_GENERAL, KEY_VIA_RUNKPI, L"常に別プロセスで使用",
            SZ_VIA_RUNKPI_DEFAULT, NULL, NULL, //default/min/max
            NULL, NULL, //list/listdesc
            L"false にすると、kbspu.kpi を 1 つだけ使用中は本体プロセスと\r\n"
            L"同じプロセス内で使用されるようになります。\r\n"
            L"(本体プロセスと異なるプロセスで使用されるよりもパフォーマンス\r\n"
            L"が向上します)\r\n"
            L"\r\n"
            L"false にする場合は、\r\n"
            L"\r\n"
            L"・本プラグインの「spuEternal.dll のパス」\r\n"
            L"・kbpsf.kpi の「spuEternal.dll のパス」\r\n"
            L"\r\n"
            L"が同じ場所にならないように(spuEternal.dll を別の場所にコピーする等)\r\n"
            L"して下さい。\r\n"
            L"プラグインの仕組み上、パスが同じかどうかを kbspu.kpi 側で判別する\r\n"
            L"ことが出来ません。\r\n"
            L"\r\n"
            L"この設定は 64bit 版の本体で動作中は意味を持ちません。\r\n"
            L""
            },//help
        {KPI_CFG_TYPE_BIN, SEC_GENERAL, KEY_CONFIG, L"設定画面を開く",
            NULL, NULL, NULL, //default/min/max
            NULL, NULL, //list/listdesc
            L"spuEternal.dll の設定画面を開きます。\r\n"
            L"spuEternal.dll の設定は spuEternal.dll 自身が管理します。\r\n"
            L"レジストリに保存されているようです。\r\n"
            L""
            },//help
        {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
    };
    for(int i = 0; sec[i].cszSection; i++){
        pEnumerator->EnumSection(&sec[i]);
    }
    for(int i = 0; key[i].cszSection; i++){
        pEnumerator->EnumKey(&key[i]);
    }
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
DWORD __fastcall kbspu_ApplyConfig(IKpiConfig *pConfig,
                               const wchar_t *cszSection,//セクション名
                               const wchar_t *cszKey,    //キー名
                               INT64  nValue, //変更後の値(BOOL/INT の場合)
                               double dValue, //変更後の値(FLOAT の場合)
                               const wchar_t *cszValue)////変更後の値(文字列)
{
    //詳細は kpi_decoder.h の IKpiDecoderModule::ApplyConfig
    //       kpi.h の kpi_CreateConfig 等を参照
    //(複数のキーの組み合わせで設定が確定する場合用)
    //プラグイン側で SetXXX しないと適用されないことに注意
    if(wcscmp(cszSection, SEC_GENERAL) == 0){
        pConfig->SetStr(cszSection, cszKey, cszValue);
        if(wcscmp(cszKey, KEY_VIA_RUNKPI) == 0){
            return KPI_CFGRET_RELOAD_KPI;
        }
        else if(wcscmp(cszKey, KEY_PATH) == 0){
            return KPI_CFGRET_RELOAD_DATA;
        }
        else if(wcscmp(cszKey, KEY_CONFIG) == 0){
            wchar_t szDll[MAX_PATH];
            pConfig->GetStr(SEC_GENERAL, KEY_PATH, szDll, sizeof(szDll), L"");
            if(KbSpuDecoder::LoadSpuPlugin(szDll)){
                KbSpuDecoder::Config();
            }
            return KPI_CFGRET_OK;
        }
    }
    //セクション/キー名ごとに適切な値を返すこと
    //cszKey[0] == 0 の場合は選択中のセクションの全てのキーを ApplyConfig し
    //終わってから呼ばれる。特別なことがなければ KPI_CFGRET_OK を返せば良い
/*
    KPI_CFGRET_OK,          //設定は即座に反映される
    KPI_CFGRET_NOTIFY,      //デコーダインスタンス等への変更通知が必要(IKpiXXX::Update()が呼ばれたら反映)
    KPI_CFGRET_RELOAD_DATA, //データの再ロードが必要(次にIKpiXXXModule::Open()が呼ばれた分から反映)
    KPI_CFGRET_RELOAD_KPI,  //プラグインの再ロードが必要
    KPI_CFGRET_REBOOT_PLAYER,//プレイヤー本体の再起動が必要(特別な事情がない限り
                             //RELOAD_KPI で足りる筈だが)
    KPI_CFGRET_REBOOT_OS,    //OS の再起動が必要
    KPI_CFGRET_UNKNOWN = (DWORD)-1
                             //不明(外部プログラムを呼び出す等、設定関係の依存
                             //コードの詳細が分からない等)
*/
    return KPI_CFGRET_OK;
}
/////////////////////////////////////////////////////////////////////////////
void __fastcall kbspu_GetSettings(IKpiConfig *pConfig, kbspu_Settings *pSettings)
{
    pConfig->GetStr(SEC_GENERAL, KEY_PATH, pSettings->szDllPath, sizeof(pSettings->szDllPath), L"");
}
/////////////////////////////////////////////////////////////////////////////
DWORD __fastcall kbspu_GetMultipleInstance(IKpiConfig *pConfig)
{
    BOOL bViaRunkpi = pConfig->GetInt(SEC_GENERAL, KEY_VIA_RUNKPI, VIA_RUNKPI_DEFAULT) != 0;
    #ifdef _DEBUG //別プロセス経由だとデバッグが面倒
        return KPI_MULTINST_ONE;
    #endif
    if(bViaRunkpi){
        return KPI_MULTINST_ZERO;
    }
    return KPI_MULTINST_ONE;
}
/////////////////////////////////////////////////////////////////////////////
