/*==========================================================================*/
/* Copyright (c) 1999 - Sykes Enterprises Inc. - All rights reserved        */
/*--------------------------------------------------------------------------*/
/* Sykes grants you ("Licensee") a non-exclusive, royalty free, license to  */
/* use, modify and redistribute this software in source and binary code     */
/* form, provided that i) this copyright notice and license appear on all   */
/* copies of the software; and ii) Licensee does not utilize the software   */
/* in a manner which is disparaging to Sykes.                               */
/*                                                                          */
/* This software is provided "AS IS", without a warranty of any kind. ALL   */
/* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING */
/* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR        */
/* PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SYKES AND ITS          */
/* LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A  */
/* RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE OR ITS           */
/* DERIVATIVES. IN NO EVENT WILL SYKES OR ITS LICENSORS BE LIABLE FOR ANY   */
/* LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,          */
/* CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND        */
/* REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR      */
/* INABILITY TO USE SOFTWARE, EVEN IF SYKES HAS BEEN ADVISED OF THE         */
/* POSSIBILITY OF SUCH DAMAGES.                                             */
/*==========================================================================*/

#include "stdafx.h"
#include "Waikoloa.h"
#include "WaikoloaDoc.h"
#include "WaikoloaView.h"

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


/*--------------------------------------------------------------------------*/
// Helper function: returns TRUE if the handle is an edit control

BOOL IsEdit
(
	CWnd*                p_pWnd
)
{
	if ( p_pWnd == NULL ) return(FALSE);

	HWND hWnd = p_pWnd->GetSafeHwnd();
	if ( hWnd == NULL ) return(FALSE);

	char szBuf[7];
	return(::GetClassName(hWnd, szBuf, 6) && (stricmp(szBuf, "Edit") == 0));
}


/*--------------------------------------------------------------------------*/

IMPLEMENT_DYNCREATE(CWaikoloaView, CFormView)

BEGIN_MESSAGE_MAP(CWaikoloaView, CFormView)
	//{{AFX_MSG_MAP(CWaikoloaView)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_QUERY, OnQuery)
	ON_LBN_SELCHANGE(IDC_LIST, OnSelchangeList)
	ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
	ON_COMMAND(ID_EDIT_CUT, OnEditCut)
	ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
	ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
	ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
	ON_BN_CLICKED(IDC_CONCORDANCE, OnConcordance)
	ON_EN_KILLFOCUS(IDC_THRESHOLD, OnKillfocusThreshold)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/*--------------------------------------------------------------------------*/

CWaikoloaView::CWaikoloaView()
	: CFormView(CWaikoloaView::IDD)
{
	//{{AFX_DATA_INIT(CWaikoloaView)
	//}}AFX_DATA_INIT

	m_nCX = 0;
	m_bInitDone = false;
}


/*--------------------------------------------------------------------------*/

CWaikoloaView::~CWaikoloaView()
{
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);

	//{{AFX_DATA_MAP(CWaikoloaView)
	DDX_Control(pDX, IDC_THRESHOLD, m_edThreshold);
	DDX_Control(pDX, IDC_CONCORDANCE, m_chkConcordance);
	DDX_Control(pDX, IDC_TOTALCOUNT, m_stTotalCount);
	DDX_Control(pDX, IDC_NBMATCHES, m_stNbMatches);
	DDX_Control(pDX, IDC_TARGET, m_edTarget);
	DDX_Control(pDX, IDC_SOURCE, m_edSource);
	DDX_Control(pDX, IDC_INDEX, m_edIndex);
	DDX_Control(pDX, IDC_THRESHOLDSPIN, m_spThreshold);
	DDX_Control(pDX, IDC_LIST, m_lbList);
	DDX_Control(pDX, IDC_QUERYTEXT, m_edQueryText);
	//}}AFX_DATA_MAP
}


/*--------------------------------------------------------------------------*/

BOOL CWaikoloaView::PreCreateWindow(CREATESTRUCT& cs)
{
	return CFormView::PreCreateWindow(cs);
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();

	GetParentFrame()->RecalcLayout();
	m_bInitDone = true;
	ResizeParentToFit();

	m_spThreshold.SetRange(1, 100);
	m_spThreshold.SetPos(GetDocument()->m_TmQ.GetThreshold());
	m_chkConcordance.SetCheck(GetDocument()->m_TmQ.GetConcordance());
}


/*--------------------------------------------------------------------------*/

#ifdef _DEBUG
void CWaikoloaView::AssertValid() const
{
	CFormView::AssertValid();
}

void CWaikoloaView::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}

CWaikoloaDoc* CWaikoloaView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWaikoloaDoc)));
	return (CWaikoloaDoc*)m_pDocument;
}
#endif //_DEBUG



/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnSize(UINT nType, int cx, int cy) 
{
	CFormView::OnSize(nType, cx, cy);
	
	CWnd* pWnd = GetDlgItem(IDC_QUERYTEXT);
	if ( pWnd == NULL ) return;

	if ( !m_bInitDone ) return;
	if ( !m_nCX )
	{
		m_nCX = cx; g_nMinCX = cx;
		m_nCY = cy; g_nMinCY = cy;
		return;
	}

	int nDeltaX;
	int nDeltaY;

	if ( cx )
	{
		nDeltaX = cx-m_nCX; m_nCX = cx;
	}
	if ( cy )
	{
		nDeltaY = cy-m_nCY; m_nCY = cy;
	}

	CRect Rect;

	// Resize query edit box (x)
	pWnd->GetWindowRect(&Rect);
	ScreenToClient(&Rect);
	Rect.right += nDeltaX;
	pWnd->SetWindowPos(NULL, 0, 0,
		Rect.right-Rect.left, Rect.bottom-Rect.top,
		SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

	// Move Sykes logo (x)
	pWnd = GetDlgItem(IDC_LOGO);
	pWnd->GetWindowRect(&Rect);
	ScreenToClient(&Rect);
	Rect.left += nDeltaX;
	pWnd->SetWindowPos(NULL, Rect.left, Rect.top,
		0, 0,
		SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

	// Resize the index-key edit box (x)
	pWnd = GetDlgItem(IDC_INDEX);
	pWnd->GetWindowRect(&Rect);
	ScreenToClient(&Rect);
	Rect.right += nDeltaX;
	pWnd->SetWindowPos(NULL, 0, 0,
		Rect.right-Rect.left, Rect.bottom-Rect.top,
		SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

	// Resize the source edit box (x)
	pWnd = GetDlgItem(IDC_SOURCE);
	pWnd->GetWindowRect(&Rect);
	ScreenToClient(&Rect);
	Rect.right += nDeltaX;
	pWnd->SetWindowPos(NULL, 0, 0,
		Rect.right-Rect.left, Rect.bottom-Rect.top,
		SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

	// Resize the target edit box (x)
	pWnd = GetDlgItem(IDC_TARGET);
	pWnd->GetWindowRect(&Rect);
	ScreenToClient(&Rect);
	Rect.right += nDeltaX;
	pWnd->SetWindowPos(NULL, 0, 0,
		Rect.right-Rect.left, Rect.bottom-Rect.top,
		SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

	// Resize the list of matches (x,y)
	pWnd = GetDlgItem(IDC_LIST);
	pWnd->GetWindowRect(&Rect);
	ScreenToClient(&Rect);
	Rect.right += nDeltaX;
	Rect.bottom += nDeltaY;
	pWnd->SetWindowPos(NULL, 0, 0,
		Rect.right-Rect.left, Rect.bottom-Rect.top,
		SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnQuery() 
{
	CString              csQuery;
	int                  nScore;
	int                  nCount;
	okLiteTMRecord       Record;
	int                  n;
	long                 lPos;
	string               sTmp;
	char                 szBuf[50];
	CString              csMsg;


	m_edQueryText.GetWindowText(csQuery);
	GetDocument()->m_TmQ.SetThreshold(m_spThreshold.GetPos());
	GetDocument()->m_TmQ.SetConcordance(m_chkConcordance.GetCheck()!=0);

	nCount = GetDocument()->m_TmQ.Query(csQuery);

	// Don't do this (not localization-friendly):
	// sprintf(szBuf, "%d Match%s", nCount, ((nCount>1) ? "es" : ""));
	// Instead do somethinglike this:
	if ( nCount > 1 ) csMsg.Format(IDS_MATCHES, nCount);
	else csMsg.Format(IDS_MATCH, nCount);
	
	m_stNbMatches.SetWindowText(csMsg);

	m_lbList.ResetContent();
	nScore = GetDocument()->m_TmQ.GetFirstMatch(Record, &lPos);
	while ( nScore )
	{
		sprintf(szBuf, "%d%%\t", nScore);
		sTmp = szBuf; sTmp += Record.m_sSource.c_str();
		n = m_lbList.AddString(sTmp.c_str());
		if ( n != LB_ERR ) m_lbList.SetItemData(n, (DWORD)lPos);
		nScore = GetDocument()->m_TmQ.GetNextMatch(Record, &lPos);
	}

	m_lbList.SetCurSel(0);
	m_lbList.SetFocus();
	OnSelchangeList();
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
	long                 lCount;
	CString              csMsg;


	// Update the total number of entries display
	lCount = GetDocument()->m_TmQ.GetTM()->GetCount();
	if ( lCount > 1 ) csMsg.Format(IDS_RECORDS, lCount);
	else csMsg.Format(IDS_RECORD, lCount);
	m_stTotalCount.SetWindowText(csMsg);

	// Re-query
	OnQuery();
}


/*--------------------------------------------------------------------------*/
// Update the edit boxes when the match selected changes

void CWaikoloaView::OnSelchangeList() 
{
	int                  n;
	char*                pData;
	int                  nLen;
	okLiteTMRecord       Record;
	long                 lPos;
	CString              csMsg;


	if ( (n = m_lbList.GetCurSel()) != LB_ERR )
	{
		lPos = (long)m_lbList.GetItemData(n);
		if ( GetDocument()->m_TmQ.GetTM()->Get(Record, lPos) )
		{
			// Source and target
			m_edSource.SetWindowText(Record.m_sSource.c_str());
			m_edTarget.SetWindowText(Record.m_sTarget.c_str());

			// Index key:
			// Sinve there is no direct access to the index from a match or
			// from a file position, we can simply re-create the key from the
			// source text and clean it up to make it human readable.
			if ( !GetDocument()->m_TmQ.GetTM()->MakeKey(
						Record.m_sSource.c_str(), &pData, &nLen) )
			{
				csMsg.LoadString(IDS_INDEXERROR);
				m_edIndex.SetWindowText(csMsg);
			}
			else
			{
				if ( !nLen )
				{
					csMsg.LoadString(IDS_INDEXEMPTY);
					m_edIndex.SetWindowText(csMsg);
				}
				else
				{
					// Do not touch the last null char
					nLen--; 
					// Convert all nulls into spaces
					for ( int i=0; i<nLen; i++ )
						if ( *(pData+i) == 0 ) *(pData+i) = ' ';
					// Show only the text keywords (skip the info at the beginning)
					m_edIndex.SetWindowText(pData+okLTM_STARTKEY);
					// Free up memory (other cases don't allocate memory)
					delete[] pData;
				}
			}
			return;
		}
	}

	// Else: nothing to show
	m_edIndex.SetWindowText("");
	m_edSource.SetWindowText("");
	m_edTarget.SetWindowText("");
}



/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnUpdateEditCopy(CCmdUI* pCmdUI) 
{
	CWnd*                pWnd = GetFocus();


	if (( pWnd == NULL ) || ( !IsEdit(pWnd) )) pCmdUI->Enable(FALSE);
	else
	{
		CEdit* pEdit = (CEdit*)pWnd;
		int nStart, nEnd;
		pEdit->GetSel(nStart, nEnd);
		pCmdUI->Enable(nStart != nEnd);
	}
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnEditCopy() 
{
	CEdit* pEdit = (CEdit*)GetFocus();
	if ( IsEdit(pEdit) ) pEdit->Copy();
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnUpdateEditCut(CCmdUI* pCmdUI) 
{
	CWnd*                pWnd = GetFocus();


	if (( pWnd == NULL ) || ( !IsEdit(pWnd) )) pCmdUI->Enable(FALSE);
	else
	{
		if ( pWnd->GetStyle() & ES_READONLY ) pCmdUI->Enable(FALSE);
		else
		{
			CEdit* pEdit = (CEdit*)pWnd;
			int nStart, nEnd;
			pEdit->GetSel(nStart, nEnd);
			pCmdUI->Enable(nStart != nEnd);
		}
	}
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnEditCut() 
{
	CEdit* pEdit = (CEdit*)GetFocus();
	if ( IsEdit(pEdit) ) pEdit->Cut();
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnUpdateEditPaste(CCmdUI* pCmdUI) 
{
	CWnd*                pWnd = GetFocus();
	

	if (( pWnd == NULL ) || ( !IsEdit(pWnd) )) pCmdUI->Enable(FALSE);
	else
	{
		if ( pWnd->GetStyle() & ES_READONLY ) pCmdUI->Enable(FALSE);
		else pCmdUI->Enable(::IsClipboardFormatAvailable(CF_TEXT));
	}
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnEditPaste() 
{
	CEdit* pEdit = (CEdit*)GetFocus();
	if ( IsEdit(pEdit) ) pEdit->Paste();
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnUpdateEditUndo(CCmdUI* pCmdUI) 
{
	CWnd*                pWnd = GetFocus();


	if (( pWnd == NULL ) || ( !IsEdit(pWnd) )) pCmdUI->Enable(FALSE);
	else
	{
		CEdit* pEdit = (CEdit*)pWnd;
		pCmdUI->Enable(pEdit->CanUndo());
	}
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnEditUndo() 
{
	CEdit* pEdit = (CEdit*)GetFocus();
	if ( IsEdit(pEdit) ) pEdit->Undo();
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnConcordance() 
{
	// Re-query the options have changed
	OnQuery();	
}


/*--------------------------------------------------------------------------*/

void CWaikoloaView::OnKillfocusThreshold() 
{
	CString              csTmp;
	int                  n;


	// Re-query if the threshold has changed
	if ( m_edThreshold.GetModify() )
	{
		m_edThreshold.GetWindowText(csTmp);
		n = atoi(csTmp);
		if ( n < 1 ) n = 1;
		if ( n > 100 ) n = 100;
		m_spThreshold.SetPos(n);
		OnQuery();
	}
}
