// waveui.cpp

// TUISPI_xxx functions ///////////////////////////////////////////////

#include "pch.h"
#include "resource.h"
#include "wavetsp.h"
#include "uicall.h"

extern HINSTANCE    g_hinst;
BOOL CenterWindow(HWND hWnd, HWND hWndCenter = 0);
extern bool GetPermanentProviderID(LPCSTR pszProvider, DWORD* pdwID);

BOOL CALLBACK CallStatusProc(
    HWND    hwnd,
    UINT    nMsg,
    WPARAM  wparam,
    LPARAM  lparam)
{
    BOOL        b = FALSE;
    CuiCall*    pCall = (CuiCall*)GetWindowLong(hwnd, GWL_USERDATA);

    switch( nMsg )
    {
    case WM_INITDIALOG:
        CenterWindow(hwnd);
        SetWindowLong(hwnd, GWL_USERDATA, lparam);
        b = TRUE;
    break;

    case WM_COMMAND:
        switch( GET_WM_COMMAND_ID(wparam, lparam) )
        {
        case IDC_DIAL:
            if( pCall->Dial(hwnd) )
            {
                EnableWindow(GetDlgItem(hwnd, IDC_DIAL), FALSE);
                EnableWindow(GetDlgItem(hwnd, IDCANCEL), FALSE);
                SetDlgItemText(hwnd, IDC_MESSAGE, "Dialing...");
            }
            else
            {
                EnableWindow(GetDlgItem(hwnd, IDC_DIAL), FALSE);
                SetDlgItemText(hwnd, IDC_MESSAGE, "Dialing failed. Check your soundcard.");
            }
        break;

        case IDCANCEL:
            pCall->Cancel();
            EndDialog(hwnd, IDCANCEL);
        break;
        }
    break;
    }

    return b;
}

// Entry point for LINE_CREATEDIALOGINSTANCE event
// from TSPI_lineMakeCall
LONG TSPIAPI TUISPI_providerGenericDialog(
    TUISPIDLLCALLBACK     lpfnUIDLLCallback,
    HTAPIDIALOGINSTANCE   htDlgInst,
    LPVOID                lpParams,
    DWORD                 dwSize,
    HANDLE                hEvent)
{
    BEGIN_PARAM_TABLE("TUISPI_providerGenericDialog")
        DWORD_IN_ENTRY(lpfnUIDLLCallback)
        DWORD_IN_ENTRY(htDlgInst)
        DWORD_IN_ENTRY(lpParams)
        DWORD_IN_ENTRY(dwSize)
        DWORD_IN_ENTRY(hEvent)
    END_PARAM_TABLE()

    // Signal TAPI it's OK to process LINE_SENDDIALOGINSTANCEDATA
    // (even though we don't use any)
    SetEvent(hEvent);

    // Pull out extra data
    LINEDIALPARAMS* pdp = (LINEDIALPARAMS*)((BYTE*)lpParams + sizeof(TSPUIDATA));
    LPCSTR          pszAddress = (LPCSTR)((BYTE*)lpParams + sizeof(TSPUIDATA) + sizeof(LINEDIALPARAMS));

    CuiCall call(htDlgInst, lpfnUIDLLCallback, pszAddress, pdp, (TSPUIDATA*)lpParams);
    DialogBoxParam(g_hinst, MAKEINTRESOURCE(IDD_CALL_STATUS), 0, CallStatusProc, (LPARAM)&call);
    return EPILOG(0);
}

BOOL CALLBACK ConfigDlgProc(
    HWND    hwnd,
    UINT    nMsg,
    WPARAM  wparam,
    LPARAM  lparam)
{
    BOOL    b = FALSE;

    switch( nMsg )
    {
    case WM_INITDIALOG:
        CenterWindow(hwnd);
        SetDlgItemText(hwnd, IDC_DTMF, "123A456B789C*0#D");
        b = TRUE;
    break;

    case WM_COMMAND:
        switch( GET_WM_COMMAND_ID(wparam, lparam) )
        {
        case IDOK:
            EndDialog(hwnd, IDOK);
        break;

        case IDCANCEL:
            EndDialog(hwnd, IDCANCEL);
        break;

        case IDC_TEST:
        {
            char    szDtmf[256];
            GetDlgItemText(hwnd, IDC_DTMF, szDtmf, DIM(szDtmf));
            if( *szDtmf )
            {
                CtDialString    ds(0, szDtmf);
                ds.Dial(WAVE_MAPPER, 250, 0);
                MessageBox(0, "Playing test digits...", "WaveTSP", MB_SETFOREGROUND);
            }
        }
        break;
        }
    break;
    }

    return b;
}
 
LONG TSPIAPI TUISPI_lineConfigDialog(
    TUISPIDLLCALLBACK   pfnUIDLLCallback,
    DWORD               dwDeviceID,
    HWND                hwndOwner,
    LPCWSTR             pszDeviceClass)
{
    BEGIN_PARAM_TABLE("TUISPI_lineConfigDialog")
        DWORD_IN_ENTRY(pfnUIDLLCallback)
        DWORD_IN_ENTRY(dwDeviceID)
        DWORD_IN_ENTRY(hwndOwner)
        STRING_IN_ENTRY(pszDeviceClass)
    END_PARAM_TABLE()
    
    DialogBox(g_hinst,
              MAKEINTRESOURCE(IDD_CONFIG),
              hwndOwner,
              ConfigDlgProc);
    
    return EPILOG(0);
}

LONG TSPIAPI TUISPI_providerInstall(
    TUISPIDLLCALLBACK   pfnUIDLLCallback,
    HWND                hwndOwner,
    DWORD               dwPermanentProviderID)
{
    BEGIN_PARAM_TABLE("TUISPI_providerInstall")
        DWORD_IN_ENTRY(pfnUIDLLCallback)
        DWORD_IN_ENTRY(hwndOwner)
        DWORD_IN_ENTRY(dwPermanentProviderID)
    END_PARAM_TABLE()
    
    LONG    tr;
    DWORD   dwID;
    tr = (GetPermanentProviderID("wavetsp.tsp", &dwID) ? LINEERR_NOMULTIPLEINSTANCE : 0);

    if( tr == 0 )
    {
        DialogBox(g_hinst,
                  MAKEINTRESOURCE(IDD_CONFIG),
                  hwndOwner,
                  ConfigDlgProc);
    }
    
    return EPILOG(tr);
}

LONG TSPIAPI TUISPI_providerConfig(
    TUISPIDLLCALLBACK   pfnUIDLLCallback,
    HWND                hwndOwner,
    DWORD               dwPermanentProviderID)
{
    BEGIN_PARAM_TABLE("TUISPI_providerConfig")
        DWORD_IN_ENTRY(pfnUIDLLCallback)
        DWORD_IN_ENTRY(hwndOwner)
        DWORD_IN_ENTRY(dwPermanentProviderID)
    END_PARAM_TABLE()
    
    DialogBox(g_hinst,
              MAKEINTRESOURCE(IDD_CONFIG),
              hwndOwner,
              ConfigDlgProc);
    
    return EPILOG(0);
}

LONG TSPIAPI TUISPI_providerRemove(
    TUISPIDLLCALLBACK   pfnUIDLLCallback,
    HWND                hwndOwner,
    DWORD               dwPermanentProviderID)
{
    BEGIN_PARAM_TABLE("TUISPI_providerRemove")
        DWORD_IN_ENTRY(pfnUIDLLCallback)
        DWORD_IN_ENTRY(hwndOwner)
        DWORD_IN_ENTRY(dwPermanentProviderID)
    END_PARAM_TABLE()
    
    return EPILOG(0);
}

// Stole this from ATL
BOOL CenterWindow(HWND hWnd, HWND hWndCenter/* = 0*/)
{
	assert(::IsWindow(hWnd));

	// determine owner window to center against
	DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
	if(hWndCenter == NULL)
	{
		if(dwStyle & WS_CHILD)
			hWndCenter = ::GetParent(hWnd);
		else
			hWndCenter = ::GetWindow(hWnd, GW_OWNER);
	}

	// get coordinates of the window relative to its parent
	RECT rcDlg;
	::GetWindowRect(hWnd, &rcDlg);
	RECT rcArea;
	RECT rcCenter;
	HWND hWndParent;
	if(!(dwStyle & WS_CHILD))
	{
		// don't center against invisible or minimized windows
		if(hWndCenter != NULL)
		{
			DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
			if(!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
				hWndCenter = NULL;
		}

		// center within screen coordinates
		::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);

		if(hWndCenter == NULL)
			rcCenter = rcArea;
		else
			::GetWindowRect(hWndCenter, &rcCenter);
	}
	else
	{
		// center within parent client coordinates
		hWndParent = ::GetParent(hWnd);
		assert(::IsWindow(hWndParent));

		::GetClientRect(hWndParent, &rcArea);
		assert(::IsWindow(hWndCenter));
		::GetClientRect(hWndCenter, &rcCenter);
		::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
	}

	int DlgWidth = rcDlg.right - rcDlg.left;
	int DlgHeight = rcDlg.bottom - rcDlg.top;

	// find dialog's upper left based on rcCenter
	int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
	int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;

	// if the dialog is outside the screen, move it inside
	if(xLeft < rcArea.left)
		xLeft = rcArea.left;
	else if(xLeft + DlgWidth > rcArea.right)
		xLeft = rcArea.right - DlgWidth;

	if(yTop < rcArea.top)
		yTop = rcArea.top;
	else if(yTop + DlgHeight > rcArea.bottom)
		yTop = rcArea.bottom - DlgHeight;

	// map screen coordinates to child coordinates
	return ::SetWindowPos(hWnd, NULL, xLeft, yTop, -1, -1,
		SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}

