// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
 
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../include/formfiller/FFL_TextField.h"
#include "../../include/formfiller/FFL_CBA_Fontmap.h"

/* ------------------------------- CFFL_TextField ------------------------------- */

CFFL_TextField::CFFL_TextField(CPDFDoc_Environment* pApp, CPDFSDK_Annot* pAnnot) :
	CFFL_FormFiller(pApp, pAnnot),
	m_pFontMap(NULL)//,
	//m_pSpellCheck(NULL)
{
	m_State.nStart = m_State.nEnd = 0;
}

CFFL_TextField::~CFFL_TextField()
{
	if (m_pFontMap)
	{
		delete m_pFontMap;
		m_pFontMap = NULL;
	}

}

PWL_CREATEPARAM CFFL_TextField::GetCreateParam()
{
	PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();

	ASSERT(m_pWidget != NULL);
	int nFlags = m_pWidget->GetFieldFlags();


	if (nFlags & FIELDFLAG_PASSWORD)
	{		
		cp.dwFlags |= PES_PASSWORD;
	}

	if (!(nFlags & FIELDFLAG_DONOTSPELLCHECK))
	{		
	}

	if (nFlags & FIELDFLAG_MULTILINE)
	{		
		cp.dwFlags |= PES_MULTILINE | PES_AUTORETURN | PES_TOP;

		if (!(nFlags & FIELDFLAG_DONOTSCROLL))
		{
			cp.dwFlags |= PWS_VSCROLL | PES_AUTOSCROLL;
		}
	}
	else
	{
		cp.dwFlags |= PES_CENTER;

		if (!(nFlags & FIELDFLAG_DONOTSCROLL))
		{
			cp.dwFlags |= PES_AUTOSCROLL;
		}
	}

	if (nFlags & FIELDFLAG_COMB)
	{		
		cp.dwFlags |= PES_CHARARRAY;
	}

	if (nFlags & FIELDFLAG_RICHTEXT)
	{		
		cp.dwFlags |= PES_RICH;
	}

	cp.dwFlags |= PES_UNDO;
	
 	switch (m_pWidget->GetAlignment())
 	{
 	default:
 	case BF_ALIGN_LEFT:
 		cp.dwFlags |= PES_LEFT;
 		break;
 	case BF_ALIGN_MIDDLE:
 		cp.dwFlags |= PES_MIDDLE;
 		break;
 	case BF_ALIGN_RIGHT:
 		cp.dwFlags |= PES_RIGHT;
 		break;
 	}

	if (!m_pFontMap)
	{
		ASSERT(this->m_pApp != NULL);
		m_pFontMap = new CBA_FontMap(m_pWidget, /*ISystemHandle::GetSystemHandler(m_pApp)*/m_pApp->GetSysHandler());
		m_pFontMap->Initial();
	}
	cp.pFontMap = m_pFontMap;
	cp.pFocusHandler = this;

	return cp;
}

CPWL_Wnd* CFFL_TextField::NewPDFWindow(const PWL_CREATEPARAM& cp, CPDFSDK_PageView* pPageView)
{
	CPWL_Edit * pWnd = new CPWL_Edit();
		pWnd->AttachFFLData(this);
	pWnd->Create(cp);



	ASSERT(m_pApp != NULL);
	CFFL_IFormFiller* pIFormFiller = m_pApp->GetIFormFiller();
	pWnd->SetFillerNotify(pIFormFiller);

	ASSERT(m_pWidget != NULL);
	FX_INT32 nMaxLen = m_pWidget->GetMaxLen();
	CFX_WideString swValue = m_pWidget->GetValue();
	
	if (nMaxLen > 0)
	{
		if (pWnd->HasFlag(PES_CHARARRAY))
		{
			pWnd->SetCharArray(nMaxLen);
			pWnd->SetAlignFormatV(PEAV_CENTER);
		}
		else
		{
			pWnd->SetLimitChar(nMaxLen);
		}
	}

	pWnd->SetText(swValue.c_str());
	return pWnd;
}


FX_BOOL	CFFL_TextField::OnChar(CPDFSDK_Annot* pAnnot, FX_UINT nChar, FX_UINT nFlags)
{
	switch (nChar)
	{
	case FWL_VKEY_Return:
 		if (!(m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE))
 		{
 			CPDFSDK_PageView* pPageView = this->GetCurPageView();
 			ASSERT(pPageView != NULL);
 			m_bValid = !m_bValid;
			CPDF_Rect rcAnnot = pAnnot->GetRect();
			m_pApp->FFI_Invalidate(pAnnot->GetPDFPage(), rcAnnot.left, rcAnnot.top, rcAnnot.right, rcAnnot.bottom);
 
 			if (m_bValid)
 			{
 				if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, TRUE))
 					pWnd->SetFocus();
 			}
 			else
 			{
 				if (CommitData(pPageView, nFlags))
 				{
 					DestroyPDFWindow(pPageView);
 					return TRUE;
 				}
 				else
 				{
 					return FALSE;
 				}
 			}
 		}
		break;
	case FWL_VKEY_Escape:
		{
			CPDFSDK_PageView* pPageView = this->GetCurPageView();
			ASSERT(pPageView != NULL);
			EscapeFiller(pPageView,TRUE);
			return TRUE;
		}
	}

	return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
}

FX_BOOL	CFFL_TextField::IsDataChanged(CPDFSDK_PageView* pPageView)
{
	ASSERT(m_pWidget != NULL);

 	if (CPWL_Edit * pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE))
 		return pEdit->GetText() != m_pWidget->GetValue();

	return FALSE;
}

void CFFL_TextField::SaveData(CPDFSDK_PageView* pPageView)
{
	ASSERT(m_pWidget != NULL);

	if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE))
	{
		CFX_WideString sOldValue = m_pWidget->GetValue();
		CFX_WideString sNewValue = pWnd->GetText();

		m_pWidget->SetValue(sNewValue, FALSE);	
		m_pWidget->ResetFieldAppearance(TRUE);
		m_pWidget->UpdateField();
		SetChangeMark();
	}
}

void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView, CPDF_AAction::AActionType type,
									PDFSDK_FieldAction& fa)
{
	switch (type)
	{
	case CPDF_AAction::KeyStroke:
		if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE))
		{
			fa.bFieldFull = pWnd->IsTextFull();	

			fa.sValue = pWnd->GetText();
			
			if (fa.bFieldFull)
			{
				fa.sChange = L"";
				fa.sChangeEx = L"";
			}
		}
		break;
	case CPDF_AAction::Validate:
		if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE))
		{
			fa.sValue = pWnd->GetText();
		}
		break;
	case CPDF_AAction::LoseFocus:
	case CPDF_AAction::GetFocus:
		ASSERT(m_pWidget != NULL);
		fa.sValue = m_pWidget->GetValue();
		break;
	default:
		break;
	}
}

void CFFL_TextField::SetActionData(CPDFSDK_PageView* pPageView, CPDF_AAction::AActionType type, 
 									const PDFSDK_FieldAction& fa)
{
	switch (type)
	{
	case CPDF_AAction::KeyStroke:
		if (CPWL_Edit * pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE))
		{
			pEdit->SetFocus();
			pEdit->SetSel(fa.nSelStart, fa.nSelEnd);
			pEdit->ReplaceSel(fa.sChange.c_str());
		}
		break;
	default:
		break;
	}
}


FX_BOOL	CFFL_TextField::IsActionDataChanged(CPDF_AAction::AActionType type, const PDFSDK_FieldAction& faOld, 
									const PDFSDK_FieldAction& faNew)
{
	switch (type)
	{
	case CPDF_AAction::KeyStroke:
		return (!faOld.bFieldFull && faOld.nSelEnd != faNew.nSelEnd) || faOld.nSelStart != faNew.nSelStart ||
			faOld.sChange != faNew.sChange;
	default:
		break;
	}

	return FALSE;
}

void CFFL_TextField::SaveState(CPDFSDK_PageView* pPageView)
{
	ASSERT(pPageView != NULL);

	if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, FALSE))
	{
		pWnd->GetSel(m_State.nStart, m_State.nEnd);
		m_State.sValue = pWnd->GetText();
	}
}

void CFFL_TextField::RestoreState(CPDFSDK_PageView* pPageView)
{
	ASSERT(pPageView != NULL);

	if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, TRUE))
	{
		pWnd->SetText(m_State.sValue.c_str());
		pWnd->SetSel(m_State.nStart, m_State.nEnd);
	}
}

CPWL_Wnd* CFFL_TextField::ResetPDFWindow(CPDFSDK_PageView* pPageView, FX_BOOL bRestoreValue)
{
	if (bRestoreValue)
		SaveState(pPageView);

	DestroyPDFWindow(pPageView);

	CPWL_Wnd* pRet = NULL;

	if (bRestoreValue)
	{
		RestoreState(pPageView);
		pRet = this->GetPDFWindow(pPageView, FALSE);
	}
	else
		pRet = this->GetPDFWindow(pPageView, TRUE);

	m_pWidget->UpdateField();
	
	return pRet;
}

void CFFL_TextField::OnSetFocus(CPWL_Wnd* pWnd)
{
	ASSERT(m_pApp != NULL);
	
 	ASSERT(pWnd != NULL);
 
 	if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT)
 	{
 		CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
		pEdit->SetCharSet(134);
		pEdit->SetCodePage(936);
 
		pEdit->SetReadyToInput();
		CFX_WideString wsText = pEdit->GetText();
		int nCharacters = wsText.GetLength();
		CFX_ByteString bsUTFText = wsText.UTF16LE_Encode();
		unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str();
		m_pApp->FFI_OnSetFieldInputFocus(m_pWidget->GetFormField(), pBuffer, nCharacters, TRUE);
 
 		pEdit->SetEditNotify(this);
 		//pUndo->BeginEdit(pDocument);
 	}
}

void CFFL_TextField::OnKillFocus(CPWL_Wnd* pWnd)
{

}

FX_BOOL	CFFL_TextField::CanCopy(CPDFSDK_Document* pDocument)
{
	return FALSE;
}

FX_BOOL CFFL_TextField::CanCut(CPDFSDK_Document* pDocument)
{
	return FALSE;
}

FX_BOOL	CFFL_TextField::CanPaste(CPDFSDK_Document* pDocument)
{
	return FALSE;
}

void CFFL_TextField::DoCopy(CPDFSDK_Document* pDocument)
{

}

void CFFL_TextField::DoCut(CPDFSDK_Document* pDocument)
{
}

void CFFL_TextField::DoPaste(CPDFSDK_Document* pDocument)
{

}

void CFFL_TextField::OnAddUndo(CPWL_Edit* pEdit)
{
}

