// tspLine.cpp

#include "pch.h"
#include "tspline.h"
#include "tspcall.h"

extern ASYNC_COMPLETION g_pfnCompletionProc;
extern HINSTANCE        g_hinst;
extern HPROVIDER        g_hProvider;
extern LINEDIALPARAMS   g_dpMin;
extern LINEDIALPARAMS   g_dpDef;
extern LINEDIALPARAMS   g_dpMax;

CtspLine::CtspLine(
    HTAPILINE   htLine,
    LINEEVENT   pfnEventProc,
    DWORD       dwDeviceID)
:
    m_pfnEventProc(pfnEventProc),
    m_htLine(htLine),
    m_nActiveCalls(0),
    m_dwDeviceID(dwDeviceID)
{
}

void CtspLine::Event(
    HTAPILINE   htLine,
    HTAPICALL   htCall,
    DWORD       dwMsg,
    DWORD       dwParam1,
    DWORD       dwParam2,
    DWORD       dwParam3)
{
    m_pfnEventProc(htLine, htCall, dwMsg, dwParam1, dwParam2, dwParam3);
}

DWORD CtspLine::GetNumActiveCalls()
{
    return m_nActiveCalls;
}

DWORD CtspLine::GetDeviceID()
{
    return m_dwDeviceID;
}

inline
DWORD NearestValue(DWORD dw, DWORD dwMin, DWORD dwDef, DWORD dwMax)
{
    if( dw == 0 ) return dwDef;
    if( dw < dwMin ) return dwMin;
    if( dw > dwMax ) return dwMax;
    return dw;
}

long CtspLine::MakeCall(
    DRV_REQUESTID       dwRequestID,
    HTAPICALL           htCall,
    LPHDRVCALL          phdCall,
    LPCWSTR             pszDestAddress,
    DWORD               dwCountryCode,
    LPLINECALLPARAMS    const pCallParams)
{                        
    // Check to see if there's already another call
    if( m_nActiveCalls )
    {
        return LINEERR_CALLUNAVAIL;
    }

    // Check media mode
    if( pCallParams &&
        pCallParams->dwMediaMode != LINEMEDIAMODE_INTERACTIVEVOICE )
    {
        return LINEERR_INVALMEDIAMODE;
    }

    // Check LINEDIALPARAMS
    LINEDIALPARAMS  dp = g_dpDef;
    if( pCallParams )
    {
        dp = pCallParams->DialParams;
        dp.dwDialPause      = NearestValue(dp.dwDialPause,      g_dpMin.dwDialPause,        g_dpDef.dwDialPause,        g_dpMax.dwDialPause);
        dp.dwDialSpeed      = NearestValue(dp.dwDialSpeed,      g_dpMin.dwDialSpeed,        g_dpDef.dwDialSpeed,        g_dpMax.dwDialSpeed);
        dp.dwDigitDuration  = NearestValue(dp.dwDigitDuration,  g_dpMin.dwDigitDuration,    g_dpDef.dwDigitDuration,    g_dpMax.dwDigitDuration);
        dp.dwWaitForDialtone= NearestValue(dp.dwWaitForDialtone,g_dpMin.dwWaitForDialtone,  g_dpDef.dwWaitForDialtone,  g_dpMax.dwWaitForDialtone);
    }

    // Set up dial string
    // If it's empty, make it ""
    if( !pszDestAddress ) pszDestAddress = L"";

    // If there's an initial 'T' or 'P' (for Tone or Pulse) in the
    // dest address then disregard it.
    if( *pszDestAddress == L'T' || *pszDestAddress == L'P' )
    {
        pszDestAddress++;
    }
    
    // Create the new call
    CtspCall*   pCall = new CtspCall(this, htCall);
    if( !pCall )
    {
        return LINEERR_NOMEM;
    }

    LONG    tr = LINEERR_OPERATIONFAILED;

    // If it's an empty string, we're done
    if( !*pszDestAddress )
    {
        g_pfnCompletionProc(dwRequestID, 0);
        tr = dwRequestID;
    }
    // If there's a string to dial, start the process
    else
    {
        // Send message to UI portion via TUISPI_providerGenericDialog
        tr = pCall->StartDial(g_hinst, g_hProvider, dwRequestID, pszDestAddress, dp);

        if( tr == 0 )
        {
            tr = dwRequestID;
        }
        else
        {
            delete pCall;
            pCall = 0;
        }
    }

    // Tell TAPI our handle to the call
    *phdCall = (HDRVCALL)pCall;

    return tr;
}
