#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <locale.h>
#include <io.h>
#include "kbdde.h"

#define SZ_KBMPLAY_EXE     _T("Kbmplay.exe")
#define SZ_KBMPLAY_MUTEX   _T("KbMedia Player")
#define SZ_KBMPLAY_TOPIC   _T("KbMedia Player")
#define SZ_KBMPLAY_SERVICE _T("KbMedia Player")

#if _MSC_VER >= 1900
#define _getts _getts_s
#endif

static BOOL ExecKbmplay(const TCHAR *cszCommandLine)
{
    //起動済みかどうか調べる
    //メインウィンドウの検索
    HWND hWnd = FindWindow(_T("TFrmMIDI"), NULL);
    if(hWnd){//すでに起動している？
        //念のため Mutex を調べてみる
        HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, SZ_KBMPLAY_MUTEX);
        if(hMutex){
            CloseHandle(hMutex);
            KbDDEClient client(NULL, SZ_KBMPLAY_SERVICE, SZ_KBMPLAY_TOPIC);
            client.Execute(cszCommandLine, 2000);
            return TRUE;
        }
    }
    {//起動する
        TCHAR szKbmplay[MAX_PATH];
        GetModuleFileName(NULL, szKbmplay, MAX_PATH);
        int lastPathDelimiter = 0;
        int i = 0;
        while(szKbmplay[i]){
#ifndef _UNICODE
            if(IsDBCSLeadByte(szKbmplay[i])){
                i += 2;continue;
            }
#endif            
            if(szKbmplay[i] == _T('\\')){
                lastPathDelimiter = i;
            }
            i++;
        }
        szKbmplay[lastPathDelimiter+1] = 0;
        lstrcat(szKbmplay, SZ_KBMPLAY_EXE);

        TCHAR szCommandLine[8192];
        lstrcpy(szCommandLine, _T("\""));
        lstrcat(szCommandLine, szKbmplay);
        lstrcat(szCommandLine, _T("\" "));
        lstrcat(szCommandLine, cszCommandLine);
        
        PROCESS_INFORMATION pi;
        STARTUPINFO s;
        ZeroMemory(&s, sizeof(s));
        ZeroMemory(&pi, sizeof(pi));
        s.cb = sizeof(s);
        CreateProcess(szKbmplay,
                      szCommandLine,
                      NULL,
                      NULL,
                      FALSE,
                      0, 
                      NULL,
                      NULL,
                      &s,
                      &pi);
        if(!pi.hProcess){
            return false;
        }
        if(WaitForInputIdle(pi.hProcess, 5000) != 0){
            CloseHandle(pi.hThread);
            CloseHandle(pi.hProcess);
            return false;
        }
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return true;
    }
}
static BOOL Request(TCHAR **ppszReturn, const TCHAR *cszCommandLine)
{
    KbDDEClient client(NULL, SZ_KBMPLAY_SERVICE, SZ_KBMPLAY_TOPIC);
    return client.Request(ppszReturn, cszCommandLine, 2000);
}

int _tmain( int argc, TCHAR *argv[ ], TCHAR *envp[ ] )
{
    _tsetlocale( LC_ALL, _T(""));
    _tprintf(_T("<< KbMedia Player DDE Client >>\n")
             _T("# で始まらない場合は XTYP_EXECUTE コマンドを発行します。\n")
             _T("例：/play\n")
             _T("# で始まる場合は XTYP_REQUEST コマンドを発行します。\n")
             _T("例：#filename\n"));
    while(1){
        _tprintf(_T("> "));
        TCHAR szCommand[8192];
        ZeroMemory(szCommand, sizeof(szCommand));
        
		if(_getts(szCommand)){
            if(!szCommand[0]){
                while(1){
                    _tprintf(_T("終了しますか?(y/n) > "));
                    if(_getts(szCommand)){
                        if(_tcsicmp(szCommand, _T("y")) == 0){
                            return 0;
                        }
                        else if(_tcsicmp(szCommand, _T("n")) == 0){
                            break;
                        }
                    }
                    else{
                        return 0;
                    }
                }
                continue;
            }
            if(szCommand[0] != _T('#')){
                ExecKbmplay(szCommand);
            }
            else{
                TCHAR *pszReturn = NULL;
                Request(&pszReturn, szCommand+1);
                if(pszReturn){
                    _tprintf(_T("returnval=%s\n"), pszReturn);
                    free(pszReturn);
                }
                else{
                    _tprintf(_T("returnval=Error!\n"));
                }
            }
        }
        else{
            break;
        }
    }
    return 0;
}
