// IncomingCallDlg.cpp : implementation file
//

#include "stdafx.h"
#include "tMonitor.h"
#include "IncomingCallDlg.h"
#include <InvisibleWindow.cpp>
#include <tWave.cpp>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CIncomingCallDlg dialog

#pragma warning(disable:4355)   // 'this' : used in base member initializer list

CIncomingCallDlg::CIncomingCallDlg(CWnd* pParent /*=NULL*/)
	:
    CDialog(CIncomingCallDlg::IDD, pParent),
    m_todo(todoNothing),
    m_wave(this)
{
	//{{AFX_DATA_INIT(CIncomingCallDlg)
	m_sName = _T("");
	m_sPhoneNo = _T("");
	//}}AFX_DATA_INIT
}


void CIncomingCallDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CIncomingCallDlg)
	DDX_Text(pDX, IDC_NAME, m_sName);
	DDX_Text(pDX, IDC_PHONE_NO, m_sPhoneNo);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CIncomingCallDlg, CDialog)
	//{{AFX_MSG_MAP(CIncomingCallDlg)
	ON_BN_CLICKED(IDC_HANG_UP, OnHangUp)
	ON_BN_CLICKED(IDC_TAKE_CALL, OnTakeCall)
	ON_BN_CLICKED(IDC_TAKE_MESSAGE, OnTakeMessage)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CIncomingCallDlg message handlers

BOOL CIncomingCallDlg::DoModeless(CWnd* pParentWnd)
{
    return Create(IDD, pParentWnd);
}

BOOL CIncomingCallDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
    m_pCall->AddSink(this);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CIncomingCallDlg::OnDestroy() 
{
	m_pCall->RemoveSink(this);
	CDialog::OnDestroy();
}

void CIncomingCallDlg::OnHangUp() 
{
    Drop();
}

void CIncomingCallDlg::OnTakeCall() 
{
    m_todo = todoTakeCall;
    GetDlgItem(IDC_TAKE_CALL)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_TAKE_MESSAGE)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_HANG_UP)->ShowWindow(SW_SHOW);

    // Answer the call and wait for OnCallState(LINECALLSTATE_CONNECTED)
    Answer();
}

void CIncomingCallDlg::OnTakeMessage() 
{
    m_todo = todoTakeMessage;
    GetDlgItem(IDC_TAKE_CALL)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_TAKE_MESSAGE)->ShowWindow(SW_HIDE);
    GetDlgItem(IDC_TAKING_MESSAGE)->ShowWindow(SW_SHOW);

    // Answer the call and wait for OnCallState(LINECALLSTATE_CONNECTED)
    Answer();
}

void CIncomingCallDlg::Drop()
{
	if( TFAILED(m_pCall->Drop()) )
    {
        AfxMessageBox(IDS_CANT_DROP_CALL);
    }

    ShowWindow(SW_HIDE);
}

void CIncomingCallDlg::Answer()
{
    if( TFAILED(m_pCall->Answer()) )
    {
        AfxMessageBox(IDS_CANT_ANSWER_CALL);
    }
}

void CIncomingCallDlg::OnCallState(
    CtCall* pCall,
    DWORD   nCallState,
    DWORD   dwParam2,
    DWORD   nCallPriviledge)
{
    switch( m_todo )
    {
    case todoTakeMessage:
        switch( nCallState )
        {
        case LINECALLSTATE_CONNECTED:
        {
            // Get the output wave device ID for the call
            CtDeviceID  did;
            if( TSUCCEEDED(did.GetIDFromCall("wave/out", m_pCall->GetHandle())) )
            {
                // Load and play the greeting (and wait for OnWaitOutDone)
                if( !m_wave.Load(AfxGetResourceHandle(), IDR_GREETING) ||
                    !m_wave.Play(did.GetDeviceID()) )
                {
                    // If load fails, fake it
                    TRACE0("Failed to load or play wav file -- faking it.\n");
                    OnWaveOutDone();
                }
            }
        }
        break;

        case LINECALLSTATE_DISCONNECTED:
            TRACE0("Recording complete\n");
            m_wave.Stop();
        break;
        }
    break;

    case todoTakeCall:
    // Set up speaker-phone mode if available
    if( nCallState == LINECALLSTATE_CONNECTED )
    {
        // Get the phone from the line
        CtDeviceID  did;
        if( TSUCCEEDED(did.GetIDFromLine("tapi/phone", m_pCall->GetLine()->GetHandle())) )
        {
            DWORD       nPhoneID = did.GetDeviceID();
            CtPhoneCaps pc;

            // Check for speakerphone mode and set it if available
            if( TSUCCEEDED(pc.GetDevCaps(nPhoneID)) &&
                (pc.GetSpeakerHookSwitchModes() & PHONEHOOKSWITCHMODE_MICSPEAKER) &&
                TSUCCEEDED(m_phone.Open(nPhoneID)) &&
                TPENDING(m_phone.SetHookSwitch(PHONEHOOKSWITCHDEV_SPEAKER,
                                               PHONEHOOKSWITCHMODE_MICSPEAKER)) )
            {
                TRACE0("Speakerphone mode set\n");
            }
            else
            {
                TRACE0("Speakerphone mode unavailable\n");

                if( m_phone.GetHandle() )
                {
                    m_phone.Close();
                }
            }
        }
    }
    break;

    case todoNothing:
        switch( nCallState )
        {
        case LINECALLSTATE_CONNECTED:
            // Someone else is dealing with it
            ShowWindow(SW_HIDE);
        break;
        }
    break;
    }
}

///////////////////////////////////////////////////////////////////
// Answering Machine events

// Greeting finished playing -- record the message
void CIncomingCallDlg::OnWaveOutDone()
{
    // Get the input wave device ID for the call
    CtDeviceID  did;
    if( TSUCCEEDED(did.GetIDFromCall("wave/in", m_pCall->GetHandle())) )
    {
        // Record a two minute message (max)
        const UINT  nSecs = 120;
        TRACE1("Recording for %d seconds\n", nSecs);

        // Record the greeting and wait for OnWaveInData
        if( !m_wave.Record(did.GetDeviceID(), nSecs) )
        {
            TRACE0("Can't record message -- dropping call\n");
            m_pCall->Drop();
            return;
        }

        // Also allow a DTMF to complete recording
        if( TFAILED(m_pCall->MonitorDigits()) )
        {
            TRACE0("Unable to terminate message with DTMF\n");
        }
    }
}

// Got a DTMF -- stop the recording
void CIncomingCallDlg::OnCallMonitorDigits(
    CtCall* pCall,
    char    cDigit,
    DWORD   nDigitMode)
{
    // If we've gotten a digit, stop recording
    m_pCall->MonitorDigits(0);
    m_wave.Stop();
    m_pCall->Drop();
}

// Message finished recording -- save it to a file
void CIncomingCallDlg::OnWaveInData()
{
    // Construct message file path name
    const CString   sMessages = "Messages";

    CString sPathName;
    GetModuleFileName(0, sPathName.GetBuffer(MAX_PATH+1), MAX_PATH);
    sPathName.ReleaseBuffer();
    sPathName = sPathName.Left(sPathName.ReverseFind('\\'));
    sPathName += '\\';
    sPathName += sMessages;
    sPathName += '\\';

    if( !SetCurrentDirectory(sPathName) &&
        !CreateDirectory(sPathName, 0) )
    {
        TRACE1("Failed to create messages directory: %s\n", (LPCSTR)sPathName);
        return;
    }

    if( !m_sName.IsEmpty() && m_sName[0] != '<' )
    {
        sPathName += m_sName;
        sPathName += ' ';
    }

    if( !m_sPhoneNo.IsEmpty() && m_sPhoneNo[0] != '<' )
    {
        sPathName += ", ";
        sPathName += m_sPhoneNo;
        sPathName += ' ';
    }

    const int   nBufLen = 64;
    CString     sDateTime;
    time_t      nTime = time(0);
    const char* pszFormat = "%a, %b %d, %H%M hours";

    strftime(sDateTime.GetBuffer(nBufLen+1), nBufLen, pszFormat, localtime(&nTime));
    sDateTime.ReleaseBuffer();

    sPathName += sDateTime;
    sPathName += ".wav";

    TRACE1("Saving wave file to %s\n", sPathName);

    // Save the message and clean out the buffer
    m_wave.Save(sPathName);
    m_wave.Close();
}

