#include <windows.h>
#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include "sapi.h"
#include "sphelper.h"
#include "spddkhlp.h"
#include "spttseng.h"
#include "spttseng_i.c"
#include "ms1033ltsmap.h" // BUGBUG: Move to somewhere... else.


#ifdef _WIN32_WCE
#define GOTO_LRETURN(hres)	{RETAILMSG(1, (_T("File: %s Line :%d, hr=%08x\n"),_T(__FILE__),__LINE__, hres)); goto LReturn;}
#define MARK(text)			{RETAILMSG(1, (_T("%s Line :%d\n"), text,__LINE__));}
#else
#define GOTO_LRETURN(hres)	{wprintf(L"Line :%d, hr=%08x\n",__LINE__, hres); goto LReturn;}
#define MARK(text)			{wprintf(L"%s Line :%d\n", text,__LINE__);}
#endif

// This code does not ship

// This code creates the registry entries for the TTS voices. The
// datafiles registered here are the ones checked in the slm source tree. This is not
// done using a reg file because we need to compute the absolute path of the datafiles
// which can be different on different machines because of different root slm directories.

#ifndef _WIN32_WCE
#define DIRS_TO_GO_BACK_VOICE      3        // Back 3 levels to 'Voices" directory
#define DIRS_TO_GO_BACK_LEX        6        // Back 3 levels to Lex Data directory
#else
#define DIRS_TO_GO_BACK_VOICE      1        // Back 3 levels to 'Voices" directory
#define DIRS_TO_GO_BACK_LEX        1        // Back 3 levels to Lex Data directory
#endif

CSpUnicodeSupport g_Unicode;

/*****************************************************************************
* CreateLexSubKey  *
*------------------*
*   Description:
*   Each TTS voice gets installed under one registry sub-key.
*   This function installs the single voice from the passed params.
*       
********************************************************************** MC ***/
HRESULT CreateLexSubKey(
    ISpObjectToken * pToken,
    const WCHAR * pszSubKeyName,
    const CLSID * pclsid,
    const WCHAR * pszFilePath, 
    const WCHAR * pszLexName,
    const WCHAR * pszPhoneMap)
{
    HRESULT hr = S_OK;

    //---------------------------------------
    // Create the lex sub-key (Lex or LTS)
    //---------------------------------------
    CComPtr<ISpObjectToken> cpSubToken;
    hr = SpGetSubTokenFromToken(pToken, pszSubKeyName, &cpSubToken, TRUE);

    if (SUCCEEDED(hr))
    {
        hr = SpSetCommonTokenData(
                cpSubToken, 
                pclsid, 
                NULL,
                0,
                NULL,
                NULL);
    }
    
    WCHAR szLexDataPath[MAX_PATH];
    if (SUCCEEDED(hr))
    {
        //--------------------------------
        // Lex DATA file location
        //--------------------------------
        wcscpy(szLexDataPath, pszFilePath);
        wcscat(szLexDataPath, pszLexName);

        hr = cpSubToken->SetStringValue(L"DataFile", szLexDataPath);
    }

    if (SUCCEEDED(hr) && pszPhoneMap)
    {
        CComPtr<ISpObjectToken> cpPhoneToken;

        if (SUCCEEDED(hr))
            hr = SpGetSubTokenFromToken(cpSubToken, L"PhoneConverter", &cpPhoneToken, TRUE);

        if (SUCCEEDED(hr))
            hr = SpSetCommonTokenData(cpPhoneToken, &CLSID_SpPhoneConverter, NULL, 0, NULL, NULL);

        if (SUCCEEDED(hr))
            hr = cpPhoneToken->SetStringValue(L"PhoneMap", pszPhoneMap);
    }

    return hr;
}

/*****************************************************************************
* CreateUISubKey  *
*-----------------*
*   Description:
*   Creates the UI SubKey under a voice.
*       
********************************************************************** AH ***/
HRESULT CreateUISubKey(
    ISpObjectToken * pToken,
    const CLSID * pclsid)
{
    HRESULT hr = S_OK;

    //-----------------------
    // Create the UI sub-key 
    //-----------------------
    CComPtr<ISpObjectToken> cpSubToken;
    hr = SpGetSubTokenFromToken(pToken, L"UI", &cpSubToken, TRUE);

    //--------------------------------------
    // Create the EngineProperties sub-key
    //--------------------------------------
    CComPtr<ISpObjectToken> cpSubSubToken;
    if ( SUCCEEDED( hr ) )
    {
        hr = SpGetSubTokenFromToken( cpSubToken, L"EngineProperties", &cpSubSubToken, TRUE );
    }

    if (SUCCEEDED(hr))
    {
        hr = SpSetCommonTokenData(
                cpSubSubToken, 
                pclsid, 
                NULL,
                0,
                NULL,
                NULL);
    }

    return hr;
}

/*****************************************************************************
* CreateVoiceSubKey  *
*--------------------*
*   Description:
*   Each TTS voice gets installed under one registry sub-key.
*   This function installs the single voice from the passed params.
*       
********************************************************************** MC ***/
HRESULT CreateVoiceSubKey(
    const WCHAR * pszSubKeyName, 
    const WCHAR  * pszDescription,
    BOOL fVendorDefault, 
    const WCHAR * pszGender,
    const WCHAR * pszAge,
    const WCHAR * pszVoicePath, 
    const WCHAR * pszVoiceName,
    const WCHAR * pszLexPath)
{
    HRESULT hr;

    CComPtr<ISpObjectToken> cpToken;
    CComPtr<ISpDataKey> cpDataKeyAttribs;
    hr = SpCreateNewTokenEx(
            SPCAT_VOICES, 
            pszSubKeyName, 
            &CLSID_MSVoiceData, 
            pszDescription,
            0x409,
            pszDescription,
            &cpToken,
            &cpDataKeyAttribs);

    if (SUCCEEDED(hr))
    {
        hr = cpDataKeyAttribs->SetStringValue(L"Name", pszSubKeyName);
    }
    
    if (SUCCEEDED(hr))
    {
        hr = cpDataKeyAttribs->SetStringValue(L"Gender", pszGender);
    }

    if (SUCCEEDED(hr))
    {
        hr = cpDataKeyAttribs->SetStringValue(L"Age", pszAge);
    }

    if (SUCCEEDED(hr))
    {
        hr = cpDataKeyAttribs->SetStringValue(L"Vendor", L"Microsoft");
    }

    if (SUCCEEDED(hr))
    {
        hr = cpDataKeyAttribs->SetStringValue(L"Language", L"409");
    }

    if (SUCCEEDED(hr) && fVendorDefault)
    {
        hr = cpDataKeyAttribs->SetStringValue(L"VendorPreferred", L"");
    }
    
    WCHAR szVoiceDataPath[MAX_PATH];
    if (SUCCEEDED(hr))
    {
        //--------------------------------
        // Voice DATA file location
        //--------------------------------
        wcscpy(szVoiceDataPath, pszVoicePath);
        wcscat(szVoiceDataPath, pszVoiceName);
        wcscat(szVoiceDataPath, L".vdt");

        hr = cpToken->SetStringValue(L"VoiceData", szVoiceDataPath);
    }
    
    if (SUCCEEDED(hr))
    {
        //--------------------------------
        // Voice DEF file location
        //--------------------------------
        wcscpy(szVoiceDataPath, pszVoicePath);
        wcscat(szVoiceDataPath, pszVoiceName);
        wcscat(szVoiceDataPath, L".vdf");

        hr = cpToken->SetStringValue(L"VoiceDef", szVoiceDataPath);
    }

    //------------------------------------------------
    // Register TTS lexicons
    //------------------------------------------------
    if (SUCCEEDED(hr))
    {
        hr = CreateLexSubKey(cpToken, L"Lex", &CLSID_SpCompressedLexicon, pszLexPath, L"LTTS1033.LXA", NULL);
    }
    if (SUCCEEDED(hr))
    {
        hr = CreateLexSubKey(cpToken, L"LTS", &CLSID_SpLTSLexicon, pszLexPath, L"r1033tts.lxa", pszms1033ltsmap);
    }
    if ( SUCCEEDED( hr ) )
    {
        hr = CreateUISubKey( cpToken, &CLSID_SpTtsEngUI );
    }

    return hr;
}

/*****************************************************************************
* main  *
*-------*
*   Description:
*    Locate the abs path to the Mary, Mike and Sam voices
*    and register them in the system registry.
*       
********************************************************************** MC ***/
int wmain()
{
    HRESULT hr = S_OK;

    CoInitialize(NULL);

    //----------------------------------------
    // Get the exe's location...
    //----------------------------------------
    WCHAR szVoiceDataPath[MAX_PATH];
    if (!g_Unicode.GetModuleFileName(NULL, szVoiceDataPath, MAX_PATH))
    {
        hr = HRESULT_FROM_WIN32(::GetLastError());
    }

    WCHAR szLexDataPath[MAX_PATH];
    if (SUCCEEDED(hr))
    {
        wcscpy(szLexDataPath, szVoiceDataPath);
    }

    //----------------------------------------
    // ...and derive abs path to VOICE data
    //----------------------------------------
    if (SUCCEEDED(hr))
    {
        // modulename is "<sapi5>\Src\TTS\msttsdrv\voices\RegVoices\debug_x86\RegVoices.exe"
        // Data is at "<sapi5>\Src\TTS\msttsdrv\voices\"
        WCHAR * psz;
        psz = szVoiceDataPath;
        
        for (int i = 0; i < DIRS_TO_GO_BACK_VOICE; i++)
        {
            psz = wcsrchr(psz, '\\');
            if (!psz)
            {
                hr = E_FAIL;
                break;
            }
            else
            {
                *psz = 0;
                psz = szVoiceDataPath;
            }
        }
    }

    if (SUCCEEDED(hr))
    {
        wcscat(szVoiceDataPath, L"\\");
    }
#ifdef _WIN32_WCE
	MARK(szVoiceDataPath);
//    if (SUCCEEDED(hr))
//    {
//        wcscat(szVoiceDataPath, L"voices\\");
//    }
//	MARK(szVoiceDataPath);
#endif	// _WIN32_WCE

    //----------------------------------------
    // Derive abs path to LEX data
    //----------------------------------------
    if (SUCCEEDED(hr))
    {
        // modulename is "<sapi5>\Src\TTS\msttsdrv\voices\RegVoices\debug_x86\RegVoices.exe"
        // Data is at "<sapi5>\Src\lexicon\data\"
        WCHAR * psz = szLexDataPath;
        for (int i = 0; i < DIRS_TO_GO_BACK_LEX; i++)
        {
            psz = wcsrchr(psz, '\\');
            if (!psz)
            {
                hr = E_FAIL;
                break;
            }
            else
            {
                *psz = 0;
                psz = szLexDataPath;
            }
        }
    }
	MARK(szLexDataPath);
    if (SUCCEEDED(hr))
    {
        wcscat(szLexDataPath, L"\\");
    }
	MARK(szLexDataPath);

    //------------------------------------------------
    // ...then register the three Microsoft voices..
    //------------------------------------------------
    if (SUCCEEDED(hr))
    {
        hr = CreateVoiceSubKey(L"MSMary", 
                               L"MS Mary", 
                               TRUE,
                               L"Female",
                               L"Adult",
                               szVoiceDataPath,
                               L"Mary",
                               szLexDataPath);
    }
/*    if (SUCCEEDED(hr))
    {
        hr = CreateVoiceSubKey(L"MSMike", 
                               L"MS Mike", 
                               FALSE,
                               L"Male", 
                               L"Adult",
                               szVoiceDataPath, 
                               L"Mike",
                               szLexDataPath);
    }
    if (SUCCEEDED(hr))
    {
        hr = CreateVoiceSubKey(L"MSSam", 
                               L"MS Sam", 
                               FALSE,
                               L"Male", 
                               L"Adult",
                               szVoiceDataPath, 
                               L"Sam",
                               szLexDataPath);
    }
*/
    CoUninitialize();

    if (FAILED(hr))
        return -1;

    return 0;
}