// GTF2TestDlg.cpp : implementation file
//

#include "stdafx.h"
#include "GTF2Test.h"
#include "GTF2TestDlg.h"
#include "Mmsystem.h"

#include "gtapi_face2.h"

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


CGTF2TestDlg* g_pMainDlg = 0;



void __stdcall local_CB_On_RecvConnected(int ch)
{
	sdkapp_msg* msg = new sdkapp_msg;
	msg->eventID = WM_SDKAPP_CONNECTED;
	msg->chanID = ch;
	
	//It is safer to post a message to Main Window instead of directly calling here as it is in low level SDK thread
	//g_pMainDlg->On_RecvConnected(ch);
	if(g_pMainDlg)
		g_pMainDlg->PostMessage(WM_SDKAPP_CONNECTED, 0, (LPARAM)msg);
}

void __stdcall local_CB_On_RecvOffered(int ch, const char* sCaller, const char* sCallee, const char* sDestAddr, \
		const char* sViaAddr, const char* sFromIP, unsigned short nFromPort)
{
	sdkapp_msg* msg = new sdkapp_msg;
	msg->eventID = WM_SDKAPP_OFFERED;
	msg->chanID = ch;
	msg->args[0] = sCaller;
	msg->args[1] = sCallee;
	msg->args[2] = sDestAddr;
	msg->args[3] = sViaAddr;
	msg->args[4] = sFromIP;
	msg->args[5].Format("%d", nFromPort);
	
	//It is safer to post a message to Main Window instead of directly calling here as it is in low level SDK thread
	//g_pMainDlg->On_RecvOffered(ch, sCaller, sCallee, sDestAddr, sViaAddr, sFromIP, nFromPort);
	if(g_pMainDlg)
		g_pMainDlg->PostMessage(WM_SDKAPP_OFFERED, 0, (LPARAM)msg);

}

void __stdcall local_CB_On_RecvDialing(int ch, const char* sCaller, const char* sCallee)
{
	sdkapp_msg* msg = new sdkapp_msg;
	msg->eventID = WM_SDKAPP_DIALING;
	msg->chanID = ch;
	msg->args[0] = sCaller;
	msg->args[1] = sCallee;	

	//It is safer to post a message to Main Window instead of directly calling here as it is in low level SDK thread
	//g_pMainDlg->On_RecvDialing(ch, sCaller, sCallee);
	if(g_pMainDlg)
		g_pMainDlg->PostMessage(WM_SDKAPP_DIALING, 0, (LPARAM)msg);
}

void __stdcall local_CB_On_RecvIdle(int ch, int code, const char* desc)
{
  	sdkapp_msg* msg = new sdkapp_msg;
	msg->eventID = WM_SDKAPP_IDLE;
	msg->chanID = ch;
	msg->args[0].Format("%d", code);
	msg->args[1] = desc;

	//It is safer to post a message to Main Window instead of directly calling here as it is in low level SDK thread
	//g_pMainDlg->On_RecvIdle(ch, code, desc);
	if(g_pMainDlg)
		g_pMainDlg->PostMessage(WM_SDKAPP_IDLE, 0, (LPARAM)msg);

}

void __stdcall local_CB_On_RecvRinging(int ch)
{
	sdkapp_msg* msg = new sdkapp_msg;
	msg->eventID = WM_SDKAPP_RINGING;
	msg->chanID = ch;    

	//It is safer to post a message to Main Window instead of directly calling here as it is in low level SDK thread
	//g_pMainDlg->On_RecvRinging(ch);
	if(g_pMainDlg)
		g_pMainDlg->PostMessage(WM_SDKAPP_RINGING, 0, (LPARAM)msg);
}

void __stdcall local_CB_On_RecvRegStatus(int user_id, int status, int regtime)
{
	sdkapp_msg* msg = new sdkapp_msg;
	msg->eventID = WM_SDKAPP_REGSTATUS;
	msg->chanID = user_id;
	msg->args[0].Format("%d", status);
	msg->args[1].Format("%d", regtime);

	//It is safer to post a message to Main Window instead of directly calling here as it is in low level SDK thread
	//g_pMainDlg->On_RecvRegStatus(user_id, status, regtime);
	if(g_pMainDlg)
		g_pMainDlg->PostMessage(WM_SDKAPP_REGSTATUS, 0, (LPARAM)msg);	
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGTF2TestDlg dialog

CGTF2TestDlg::CGTF2TestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CGTF2TestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CGTF2TestDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	g_pMainDlg = this;
}

void CGTF2TestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CGTF2TestDlg)
	DDX_Control(pDX, IDC_EDIT_SIP_ADDR, m_editSipAddr);
	DDX_Control(pDX, IDC_STATIC_LOG, m_staticLog);
	DDX_Control(pDX, IDC_BUTTON_HUNGUP, m_btnHungup);
	DDX_Control(pDX, IDC_BUTTON_DIAL, m_btnDial);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CGTF2TestDlg, CDialog)
	//{{AFX_MSG_MAP(CGTF2TestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTON_DIAL, OnButtonDial)
	ON_BN_CLICKED(IDC_BUTTON_HUNGUP, OnButtonHungup)
	ON_MESSAGE(WM_SDKAPP_OFFERED, OnSDKAppMessage)
	ON_MESSAGE(WM_SDKAPP_DIALING, OnSDKAppMessage)
	ON_MESSAGE(WM_SDKAPP_RINGING, OnSDKAppMessage)
	ON_MESSAGE(WM_SDKAPP_CONNECTED, OnSDKAppMessage)
	ON_MESSAGE(WM_SDKAPP_IDLE, OnSDKAppMessage)
	ON_MESSAGE(WM_SDKAPP_REGSTATUS, OnSDKAppMessage)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGTF2TestDlg message handlers

BOOL CGTF2TestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here

	GTAPI_Create_Env();

	GTAPI_SetMainWnd(m_hWnd);

	GTAPI_CFG_SetValue("gtsrv.sip.server.model", "0"); //client phone

    GTAPI_CFG_SetValue("gtsrv.sip.ip.port", "5890");
    GTAPI_CFG_SetValue("gtsrv.sip.rtpstartrange", "8400");
	GTAPI_CFG_SetValue("gtsrv.sip.rtpendrange", "8800");

    GTAPI_CFG_SetValue("gtsrv.sip.boardnum.per.server", "1");
    GTAPI_CFG_SetValue("gtsrv.sip.spannum.per.board", "1");
    GTAPI_CFG_SetValue("gtsrv.sip.channum.per.span", "1");

    GTAPI_CFG_SetValue("gtsrv.channel.inbound", "0-3");
    GTAPI_CFG_SetValue("gtsrv.channel.outbound", "4-15");

    GTAPI_CFG_SetValue("gtsrv.net.port", "8914");

	GTAPI_SetCB_On_RecvConnected(local_CB_On_RecvConnected);
	GTAPI_SetCB_On_RecvOffered(local_CB_On_RecvOffered);
	GTAPI_SetCB_On_RecvDialing(local_CB_On_RecvDialing);
	GTAPI_SetCB_On_RecvIdle(local_CB_On_RecvIdle);
	GTAPI_SetCB_On_RecvRinging(local_CB_On_RecvRinging);
	GTAPI_SetCB_On_RecvRegStatus(local_CB_On_RecvRegStatus);

	if(!GTAPI_StartServer())
		MessageBox("GTAPI_StartServer Failed! Please check if SIP port is being used by another application!", "Error");

	m_btnDial.EnableWindow(TRUE);
	m_btnDial.SetWindowText("Dial");

	m_btnHungup.EnableWindow(FALSE);

	m_editSipAddr.SetWindowText("8888@sip.pcbest.net");
	m_staticLog.SetWindowText("IDLE");
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CGTF2TestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CGTF2TestDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CGTF2TestDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CGTF2TestDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
	GTAPI_StopServer();

	GTAPI_Destroy_Env();

}

void CGTF2TestDlg::OnButtonDial() 
{
	// TODO: Add your control notification handler code here
	char sTemp[128];
	char sTemp1[256];

	m_btnDial.GetWindowText(sTemp, 128);

	if(stricmp(sTemp, "Answer") == 0)
	{
		//new call to answer
		GTAPI_Send_Answer(0);
	}
	else
	{
		m_editSipAddr.GetWindowText(sTemp, 128);

		sprintf(sTemp1, "<sip:%s>", sTemp);

		GTAPI_Send_Make(0, sTemp1, "");
	}
}

void CGTF2TestDlg::OnButtonHungup() 
{
	// TODO: Add your control notification handler code here
	GTAPI_Send_HangUp(0, 0, "");
}


void CGTF2TestDlg::On_RecvConnected(int ch)
{
	GTAPI_StopSound();

	m_btnDial.EnableWindow(FALSE);
	m_btnHungup.EnableWindow(TRUE);

	m_staticLog.SetWindowText("Connected");

	GTAPI_Send_StartDXAudio(0);
}

void CGTF2TestDlg::On_RecvOffered(int ch, const char* sCaller, const char* sCallee, const char* sDestAddr, \
			const char* sViaAddr, const char* sFromIP, unsigned short nFromPort)
{
    GTAPI_StopSound();
    GTAPI_PlayLocalRingSound();

	m_btnDial.EnableWindow(TRUE);
	m_btnDial.SetWindowText("Answer");

	m_btnHungup.EnableWindow(TRUE);

	m_staticLog.SetWindowText("New Call coming in");
}

void CGTF2TestDlg::On_RecvDialing(int ch, const char* sCaller, const char* sCallee)
{
	m_btnDial.EnableWindow(TRUE);
	m_btnHungup.EnableWindow(TRUE);

	m_staticLog.SetWindowText("Dialing out");
}

void CGTF2TestDlg::On_RecvIdle(int ch, int code, const char* desc)
{
    GTAPI_StopSound();

	m_btnDial.EnableWindow(TRUE);
	m_btnDial.SetWindowText("Dial");

	m_btnHungup.EnableWindow(FALSE);

	m_staticLog.SetWindowText("IDLE");
}

void CGTF2TestDlg::On_RecvRinging(int ch)
{
    GTAPI_StopSound();
    GTAPI_PlayRemoteRingSound();

	m_btnDial.EnableWindow(TRUE);
	m_btnHungup.EnableWindow(TRUE);

	m_staticLog.SetWindowText("Remote Side Ringing");
}

void CGTF2TestDlg::On_RecvRegStatus(int user_id, int status, int regtime)
{
}


LRESULT CGTF2TestDlg::OnSDKAppMessage(WPARAM wParam, LPARAM lParam)
{
	sdkapp_msg* msg = (sdkapp_msg*)lParam;
	if(!msg) return 0;
	
	switch(msg->eventID)
	{
		case WM_SDKAPP_OFFERED:
		On_RecvOffered(msg->chanID, msg->args[0], msg->args[1], msg->args[2], msg->args[3], msg->args[4], atoi(msg->args[5]));
		break;
		case WM_SDKAPP_DIALING:
		On_RecvDialing(msg->chanID, msg->args[0], msg->args[1]);
		break;
		case WM_SDKAPP_RINGING:
		On_RecvRinging(msg->chanID);
		break;
		case WM_SDKAPP_CONNECTED:
		On_RecvConnected(msg->chanID);
		break;
		case WM_SDKAPP_IDLE:
		On_RecvIdle(msg->chanID, atoi(msg->args[0]), msg->args[1]);
		break;
		case WM_SDKAPP_REGSTATUS:
		On_RecvRegStatus(msg->chanID, atoi(msg->args[0]), atoi(msg->args[1]));
		break;
	}

	delete msg;
}

