// HTTPSettingsPage.cpp : implementation file
//

#include "stdafx.h"
#include "wmsoapsvccp.h"
#include "HTTPSettingsPage.h"
#include "AddMIMETypeDlg.h"
#include "EditMIMETypeDlg.h"
#include "..\soap_source\SOAPAutomationProxy.h"
#include "..\soap_source\bytearrayconv.h"
#include "..\soap_source\WMSOAPWSDLClient.h"


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

/////////////////////////////////////////////////////////////////////////////
// CHTTPSettingsPage property page

IMPLEMENT_DYNCREATE(CHTTPSettingsPage, CPropertyPage)

CHTTPSettingsPage::CHTTPSettingsPage() : CPropertyPage(CHTTPSettingsPage::IDD)
{
	//{{AFX_DATA_INIT(CHTTPSettingsPage)
	m_strDocBasePath = _T("");
	m_strDefaultFilePath = _T("");
	//}}AFX_DATA_INIT
	m_bDirty = FALSE;
}

CHTTPSettingsPage::~CHTTPSettingsPage()
{
}

void CHTTPSettingsPage::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHTTPSettingsPage)
	DDX_Control(pDX, IDC_LIST_MIMETYPES, m_listMIMETypes);
	DDX_Text(pDX, IDC_EDIT_DOC_BASE, m_strDocBasePath);
	DDX_Text(pDX, IDC_EDIT_DOC_DEFAULT, m_strDefaultFilePath);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CHTTPSettingsPage, CPropertyPage)
	//{{AFX_MSG_MAP(CHTTPSettingsPage)
	ON_EN_CHANGE(IDC_EDIT_DOC_BASE, OnChangeEditDocBase)
	ON_EN_CHANGE(IDC_EDIT_DOC_DEFAULT, OnChangeEditDocDefault)
	ON_BN_CLICKED(IDC_BUTTON_ADD, OnButtonAdd)
	ON_BN_CLICKED(IDC_BUTTON_EDIT, OnButtonEdit)
	ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHTTPSettingsPage message handlers

BOOL CHTTPSettingsPage::OnInitDialog() 
{
	CPropertyPage::OnInitDialog();
	
	if (SetupMIMETypesList() == FALSE)
	{
		AfxMessageBox(_T("Failed to intialize HTTP Settings list!"));
	}
	CWSSCPApp *pApp = (CWSSCPApp *)AfxGetApp();
	if (QueryHTTPSettings() == FALSE && pApp->m_bStaleNonce == true)
	{
		// server nonce stale, reauthenticate
		if (QueryHTTPSettings() == FALSE)
		{
			AfxMessageBox(_T("Failed to obtain HTTP Settings from Server!"));
		}
	}

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CHTTPSettingsPage::OnOK() 
{
	UpdateData(TRUE);
	CWSSCPApp *pApp = (CWSSCPApp *)AfxGetApp();
	if (m_bDirty == TRUE && UpdateHTTPSettings() == FALSE && pApp->m_bStaleNonce == true)
	{
		// server nonce stale, reauthenticate
		if (UpdateHTTPSettings() == FALSE)
		{
			AfxMessageBox(_T("Error: Failed to update HTTP Settings on Server!"));
		}
	}
	
	CPropertyPage::OnOK();
}

BOOL CHTTPSettingsPage::SetupMIMETypesList()
{
	char szBuffer[LIST_ITEM_BUFFER_SIZE];
	char *ppszTitles[] = {_T("Extension"), _T("MIME Type")};
	const int nNumCols = 2;

	// calculate and set column width
	RECT r;
	m_listMIMETypes.GetClientRect(&r);
	LV_COLUMN lvc;
	float f = (float)r.right / (float)(nNumCols + 1);

	for (int i = 0; i < nNumCols; i++)
	{
		lstrcpy(szBuffer, ppszTitles[i]);
	
		lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
		lvc.fmt = LVCFMT_LEFT;
		lvc.pszText = szBuffer;
		lvc.iSubItem = i;

		if (i == 1)
			lvc.cx = (int)(f * 2.0);
		else
			lvc.cx = (int)f;

		if (m_listMIMETypes.InsertColumn(i,&lvc) == -1)
		{
			return FALSE;
		}
	}
	return TRUE;
}

void CHTTPSettingsPage::OnChangeEditDocBase() 
{
	SetModified(TRUE);
	m_bDirty = TRUE;
}

void CHTTPSettingsPage::OnChangeEditDocDefault() 
{
	SetModified(TRUE);
	m_bDirty = TRUE;
}

BOOL CHTTPSettingsPage::QueryHTTPSettings()
{
	CWaitCursor wait;
	CWSSCPApp *pApp = (CWSSCPApp *)AfxGetApp();
	// renew the message object
	if (pApp->m_SOAPClient.NewMessage() == false)
	{
		return FALSE;
	}
	// method
	wstring wstrMethodName = L"GetHTTPSettings";
	// set up call
	_variant_t Args[3];
	wstring Names[3];
	_variant_t varReturn;

	// Doc root path
	Names[0] = L"DocRootPath";

	Names[1] = L"DefaultFilePath";

	Args[2].vt = VT_VARIANT | VT_ARRAY;
	Args[2].parray = NULL;
	Names[2] = L"MIMETypes";

	int nNumArgs = 3;

	// generate SOAP request message headers
	pApp->BuildRequestHeaders();

	// message buffer strings
	string strRequestXML;
	string strResponseXML;

	// attempt method invocation
	bool bFault = false;
	if (pApp->m_SOAPClient.InvokeSOAPMethod(wstrMethodName,
											Names,
											Args,
											nNumArgs,
											varReturn) == false)
	{
		bFault = true;
	}
	if (pApp->m_bViewBuffers == true)
	{
		MessageBox(pApp->m_SOAPClient.GetXMLOut(), "Request Message", MB_OK);
		MessageBox(pApp->m_SOAPClient.GetXMLIn(), "Response Message", MB_OK);
	}

	// load response message headers
	pApp->GetResponseHeaders();

	if (bFault == true ||
		varReturn.boolVal == VARIANT_FALSE ||
		pApp->m_SOAPClient.IsSOAPFault() == true ||
		pApp->AuthServer() == false)
	{
		return FALSE;
	}
	// extract Document base path
	m_strDocBasePath = Args[0].bstrVal;
	// extract Default file path
	m_strDefaultFilePath = Args[1].bstrVal;
	// extract info from SAFEARRAY
	VARIANT *pVar = NULL;
	SAFEARRAY *pArray = Args[2].parray;
	const long lNumDims = 2;
	long *arrIndex = new long[lNumDims];
	char szBuffer[LIST_ITEM_BUFFER_SIZE];
	LV_ITEM item;
	item.mask = LVIF_TEXT;
	item.pszText = szBuffer;
	// lock array
	SafeArrayLock(pArray);
	// array format: [rows][cols] i == rows, j == cols
	// leftmost dimension (rows) is in rgsabound[0]
	for (int i = pArray->rgsabound[0].lLbound;
			i < (pArray->rgsabound[0].lLbound + (long)pArray->rgsabound[0].cElements);
			i++)
	{
		// leftmost dimension (rows) is arrIndex[1] (opposite of rgsabound[])
		arrIndex[1] = i;
		// rightmost dimension (cols) is in rgsabound[1]
		for (int j = pArray->rgsabound[1].lLbound;
			j < (pArray->rgsabound[1].lLbound + (long)pArray->rgsabound[1].cElements);
			j++)
		{
			// rightmost dimension (cols) is arrIndex[0]
			arrIndex[0] = j;
			SafeArrayPtrOfIndex(pArray, arrIndex, (void **)&pVar);
			CString strTemp(pVar->bstrVal);
			// place items in columns
			lstrcpy(szBuffer, (LPCTSTR)strTemp);
			item.iItem = i - pArray->rgsabound[0].lLbound;
			item.iSubItem = j - pArray->rgsabound[1].lLbound;
			// new item??
			if (item.iSubItem == 0)
			{
				m_listMIMETypes.InsertItem(&item);
			}
			else
			{
				m_listMIMETypes.SetItem(&item);
			}
		}
	}
	SafeArrayUnlock(pArray);
	UpdateData(FALSE);
	m_listMIMETypes.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
	m_listMIMETypes.SetFocus();
	return TRUE;
}

BOOL CHTTPSettingsPage::UpdateHTTPSettings()
{
	CWaitCursor wait;
	CWSSCPApp *pApp = (CWSSCPApp *)AfxGetApp();
	// renew the message object
	if (pApp->m_SOAPClient.NewMessage() == false)
	{
		return FALSE;
	}
	// method
	wstring wstrMethodName = L"SetHTTPSettings";
	// set up call
	_variant_t Args[3];
	wstring Names[3];
	_variant_t varReturn;
	
	// Document root path
	Args[0] = m_strDocBasePath.AllocSysString();
	Names[0] = L"DocRootPath";
	// Default file path
	Args[1] = m_strDefaultFilePath.AllocSysString();
	Names[1] = L"DefaultFilePath";

	// set up SAFEARRAY param
	long lNumDims = 2;
	SAFEARRAYBOUND *pBounds = new SAFEARRAYBOUND[lNumDims];
	// reverse major ordering - SAFEARRAY is the reverse of SOAP-ENC
	// in terms of the SAFEARRAYBOUND array passed to SafeArrayCreate()
	// rightmost dimension (cols) goes in pBounds[0]
	pBounds[0].lLbound = 0;
	pBounds[0].cElements = 2;
	// leftmost dimension (rows) goes in pBounds[1]
	int nNumServices = m_listMIMETypes.GetItemCount();
	pBounds[1].lLbound = 0;
	pBounds[1].cElements = nNumServices;
	// Note: these will be found in reverse order in pArray->rgsabound[]
	SAFEARRAY *pArray = SafeArrayCreate(VT_VARIANT, lNumDims, pBounds);
	delete [] pBounds;
	if (pArray == NULL)
	{
		return FALSE;
	}
	// fill array
	char szBuffer[LIST_ITEM_BUFFER_SIZE];
	LV_ITEM item;
	item.mask = LVIF_TEXT;
	item.pszText = szBuffer;
	item.cchTextMax = LIST_ITEM_BUFFER_SIZE;
	long *arrIndex = new long[lNumDims];
	for (int i = 0; i < nNumServices; i++)
	{
		item.iItem = i;
		// leftmost dimension (rows) is arrIndex[1]
		arrIndex[1] = i;
		for (int j = 0; j < 2; j++)
		{
			item.iSubItem = j;
			// rightmost dimension (cols) is arrIndex[0]
			arrIndex[0] = j;
			// get subitem
			if (m_listMIMETypes.GetItem(&item) != 0)
			{
				_variant_t varTemp;
				varTemp = item.pszText;
				SafeArrayPutElement(pArray, arrIndex, &varTemp);
			}
		}
	}
	Args[2].vt = VT_VARIANT | VT_ARRAY;
	Args[2].parray = pArray;
	Names[2] = L"MIMETypes";

	int nNumArgs = 3;

	// generate SOAP request message headers
	pApp->BuildRequestHeaders();

	// message buffer strings
	string strRequestXML;
	string strResponseXML;

	// attempt method invocation
	bool bFault = false;
	if (pApp->m_SOAPClient.InvokeSOAPMethod(wstrMethodName,
											Names,
											Args,
											nNumArgs,
											varReturn) == false)
	{
		bFault = true;
	}
	if (pApp->m_bViewBuffers == true)
	{
		MessageBox(pApp->m_SOAPClient.GetXMLOut(), "Request Message", MB_OK);
		MessageBox(pApp->m_SOAPClient.GetXMLIn(), "Response Message", MB_OK);
	}
	// load response message headers
	pApp->GetResponseHeaders();

	if (bFault == true ||
		varReturn.boolVal == VARIANT_FALSE ||
		pApp->m_SOAPClient.IsSOAPFault() == true ||
		pApp->AuthServer() == false)
	{
		return FALSE;
	}
	m_bDirty = FALSE;
	return TRUE;
}

void CHTTPSettingsPage::OnButtonAdd() 
{
	CAddMIMETypeDlg dlg;

	if (dlg.DoModal() == IDOK)
	{
		char szBuffer[LIST_ITEM_BUFFER_SIZE];
		// check for duplication
		int nNumTypes = m_listMIMETypes.GetItemCount();
		for (int i = 0; i < nNumTypes; i++)
		{
			LV_ITEM item;
			item.mask = LVIF_TEXT;
			item.iItem = i;
			item.iSubItem = 0;
			item.pszText = szBuffer;
			item.cchTextMax = LIST_ITEM_BUFFER_SIZE;
			// get subitem0 (extension) in 1st column
			if (m_listMIMETypes.GetItem(&item) != 0)
			{
				CString strData = item.pszText;
				if (dlg.m_strExtension == strData)
				{
					strData.Format(_T("Error: File Extension <%s> already mapped!\nNew mapping not created."),
										dlg.m_strExtension);
					AfxMessageBox(strData);
					return;
				}
			}
		}
		// place subitem0 (Extension) in 1st column
		LV_ITEM item;
		item.mask = LVIF_TEXT;
		item.iItem = m_listMIMETypes.GetItemCount();
		item.iSubItem = 0;
		item.pszText = dlg.m_strExtension.GetBuffer(1);
		m_listMIMETypes.InsertItem(&item);
		dlg.m_strExtension.ReleaseBuffer(-1);
		// place subitem1 (MIME Type) in 2nd column
		item.iSubItem = 1;
		item.pszText = dlg.m_strMIMEType.GetBuffer(1);
		m_listMIMETypes.SetItem(&item);
		dlg.m_strMIMEType.ReleaseBuffer(-1);
		// done
		SetModified();
		m_bDirty = TRUE;
	}
}

void CHTTPSettingsPage::OnButtonEdit() 
{
	int nItem = m_listMIMETypes.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);

	if (nItem == -1)
	{
		return;
	}
	char szBuffer[LIST_ITEM_BUFFER_SIZE];
	CEditMIMETypeDlg dlg;

	LV_ITEM item;
	item.mask = LVIF_TEXT;
	item.iItem = nItem;
	item.iSubItem = 0;
	item.pszText = szBuffer;
	item.cchTextMax = LIST_ITEM_BUFFER_SIZE;
	// get subitem0 (Extension) in 1st column
	if (m_listMIMETypes.GetItem(&item) == 0)
	{
		return;
	}
	dlg.m_strExtension = szBuffer;

	// get subitem1 (MIME Type) in 2nd column
	item.iSubItem = 1;
	if (m_listMIMETypes.GetItem(&item) == 0)
	{
		return;
	}
	dlg.m_strMIMEType = szBuffer;

	if (dlg.DoModal() == IDOK)
	{
		// place subitem1 (Service ProgID) in 2nd column
		item.iSubItem = 1;
		item.pszText = dlg.m_strMIMEType.GetBuffer(1);
		m_listMIMETypes.SetItem(&item);
		dlg.m_strMIMEType.ReleaseBuffer(-1);
		// done
		SetModified();
		m_bDirty = TRUE;
	}
}

void CHTTPSettingsPage::OnButtonDelete() 
{
	int nItem = m_listMIMETypes.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);

	if (nItem != -1)
	{
		char szBuffer[LIST_ITEM_BUFFER_SIZE];

		LV_ITEM item;
		item.mask = LVIF_TEXT;
		item.iItem = nItem;
		item.iSubItem = 0;
		item.pszText = szBuffer;
		item.cchTextMax = LIST_ITEM_BUFFER_SIZE;
		if (m_listMIMETypes.GetItem(&item) == 0)
		{
			return;
		}

		CString strMsg = _T("Are you sure you want to delete the\nMIME Type mapping for file extension: ");
		strMsg += szBuffer;
		strMsg += _T(" ?");
	
		if (AfxMessageBox(strMsg, MB_YESNO) == IDYES)
		{
			// delete Service from list ctrl
			m_listMIMETypes.DeleteItem(nItem);
			// the deed is done
			SetModified();
			m_bDirty = TRUE;
		}
	}
}
