// 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/pdfwindow/PDFWindow.h"
#include "../../include/pdfwindow/PWL_Wnd.h"
#include "../../include/pdfwindow/PWL_EditCtrl.h"
#include "../../include/pdfwindow/PWL_ScrollBar.h"
#include "../../include/pdfwindow/PWL_Utils.h"
#include "../../include/pdfwindow/PWL_Caret.h"
#include "../../include/pdfwindow/PWL_FontMap.h"

#define IsFloatZero(f)						((f) < 0.0001 && (f) > -0.0001)
#define IsFloatBigger(fa,fb)				((fa) > (fb) && !IsFloatZero((fa) - (fb)))
#define IsFloatSmaller(fa,fb)				((fa) < (fb) && !IsFloatZero((fa) - (fb)))
#define IsFloatEqual(fa,fb)					IsFloatZero((fa)-(fb))

/* ---------------------------- CPWL_EditCtrl ------------------------------ */

CPWL_EditCtrl::CPWL_EditCtrl() :
	m_pEdit(NULL),
	m_pEditCaret(NULL),
	m_bMouseDown(FALSE),
	m_pEditNotify(NULL),
	m_nCharSet(DEFAULT_CHARSET),
	m_nCodePage(0)
{
	m_pEdit = IFX_Edit::NewEdit();
	ASSERT(m_pEdit != NULL);
}

CPWL_EditCtrl::~CPWL_EditCtrl()
{
	IFX_Edit::DelEdit(m_pEdit);
}

void CPWL_EditCtrl::OnCreate(PWL_CREATEPARAM & cp)
{
	cp.eCursorType = FXCT_VBEAM;
}

void CPWL_EditCtrl::OnCreated()
{
	SetFontSize(this->GetCreationParam().fFontSize);

	m_pEdit->SetFontMap(this->GetFontMap());
	m_pEdit->SetNotify(this);
	m_pEdit->Initialize();
}

FX_BOOL CPWL_EditCtrl::IsWndHorV()
{
	CPDF_Matrix mt = GetWindowMatrix();
	CPDF_Point point1(0,1);
	CPDF_Point point2(1,1);

	mt.Transform(point1.x, point1.y);
	mt.Transform(point2.x, point2.y);

	return point2.y == point1.y;
}

void CPWL_EditCtrl::SetCursor()
{
	if (IsValid()) 
	{
		if (IFX_SystemHandler* pSH = GetSystemHandler())
		{
			if (IsWndHorV())
				pSH->SetCursor(FXCT_VBEAM);
			else
				pSH->SetCursor(FXCT_HBEAM);
		}
	}
}

void CPWL_EditCtrl::RePosChildWnd()
{
	m_pEdit->SetPlateRect(GetClientRect());
}

void CPWL_EditCtrl::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, FX_INTPTR wParam, FX_INTPTR lParam)
{
	CPWL_Wnd::OnNotify(pWnd,msg,wParam,lParam);

	switch (msg)
	{
		case PNM_SETSCROLLINFO:
			switch (wParam)
			{
				case SBT_VSCROLL:
					if (CPWL_Wnd * pChild = GetVScrollBar())
					{
						pChild->OnNotify(pWnd,PNM_SETSCROLLINFO,wParam,lParam);
					}
					break;
			}
			break;
		case PNM_SETSCROLLPOS:			
			switch (wParam)
			{
				case SBT_VSCROLL:
					if (CPWL_Wnd * pChild = GetVScrollBar())
					{
						pChild->OnNotify(pWnd,PNM_SETSCROLLPOS,wParam,lParam);
					}
					break;
			}
			break;
		case PNM_SCROLLWINDOW:
			{
				FX_FLOAT fPos = *(FX_FLOAT*)lParam;
				switch (wParam)
				{
					case SBT_VSCROLL:
						m_pEdit->SetScrollPos(CPDF_Point(m_pEdit->GetScrollPos().x,fPos));
						break;
				}
			}
			break;
		case PNM_SETCARETINFO:
			{
				if (PWL_CARET_INFO * pCaretInfo = (PWL_CARET_INFO *)wParam)
				{
					this->SetCaret(pCaretInfo->bVisible,
						pCaretInfo->ptHead,
						pCaretInfo->ptFoot);					
				}
			}
			break;
	}
}

void CPWL_EditCtrl::CreateChildWnd(const PWL_CREATEPARAM & cp)
{
	if (!IsReadOnly())
		CreateEditCaret(cp);
}

void CPWL_EditCtrl::CreateEditCaret(const PWL_CREATEPARAM & cp)
{
	if (!m_pEditCaret)
	{
		m_pEditCaret = new CPWL_Caret;	
		m_pEditCaret->SetInvalidRect(GetClientRect());

		PWL_CREATEPARAM	ecp = cp;
		ecp.pParentWnd = this;
		ecp.dwFlags = PWS_CHILD | PWS_NOREFRESHCLIP;
		ecp.dwBorderWidth = 0;
		ecp.nBorderStyle = PBS_SOLID;
		ecp.rcRectWnd = CPDF_Rect(0,0,0,0);

		m_pEditCaret->Create(ecp);
	}
}

void CPWL_EditCtrl::SetFontSize(FX_FLOAT fFontSize)
{
	m_pEdit->SetFontSize(fFontSize);
}

FX_FLOAT CPWL_EditCtrl::GetFontSize() const
{
	return m_pEdit->GetFontSize();
}

FX_BOOL CPWL_EditCtrl::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag)
{
	if (m_bMouseDown) return TRUE;

	FX_BOOL bRet = CPWL_Wnd::OnKeyDown(nChar,nFlag);

	//FILTER
	switch (nChar)
	{
	default:
		return FALSE;
	case FWL_VKEY_Delete:
	case FWL_VKEY_Up:
	case FWL_VKEY_Down:
	case FWL_VKEY_Left:
	case FWL_VKEY_Right:
	case FWL_VKEY_Home:
	case FWL_VKEY_End:
	case FWL_VKEY_Insert:
	case 'C':
	case 'V':
	case 'X':
	case 'A':
	case 'Z':
	case 'c':
	case 'v':
	case 'x':
	case 'a':
	case 'z':
		break;
	}

	if (nChar == FWL_VKEY_Delete)
	{
		if (m_pEdit->IsSelected())
			nChar = FWL_VKEY_Unknown;
	}

	switch (nChar)
	{
		case FWL_VKEY_Delete:	
			Delete();
			return TRUE;
		case FWL_VKEY_Insert:
			if (IsSHIFTpressed(nFlag))
				PasteText();
			return TRUE;
		case FWL_VKEY_Up:
			m_pEdit->OnVK_UP(IsSHIFTpressed(nFlag),FALSE);
			return TRUE;
		case FWL_VKEY_Down:
			m_pEdit->OnVK_DOWN(IsSHIFTpressed(nFlag),FALSE);
			return TRUE;
		case FWL_VKEY_Left:
			m_pEdit->OnVK_LEFT(IsSHIFTpressed(nFlag),FALSE);
			return TRUE;
		case FWL_VKEY_Right:
			m_pEdit->OnVK_RIGHT(IsSHIFTpressed(nFlag),FALSE);
			return TRUE;
		case FWL_VKEY_Home:
			m_pEdit->OnVK_HOME(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
			return TRUE;
		case FWL_VKEY_End:
			m_pEdit->OnVK_END(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
			return TRUE;
		case FWL_VKEY_Unknown:
			if (!IsSHIFTpressed(nFlag))
				Clear();
			else
				CutText();
			return TRUE;
		default:
			break;
	}
	
	return bRet;
}

FX_BOOL CPWL_EditCtrl::OnChar(FX_WORD nChar, FX_DWORD nFlag)
{
	if (m_bMouseDown) return TRUE;

	CPWL_Wnd::OnChar(nChar,nFlag);

	//FILTER
	switch (nChar)
	{
		case 0x0A:
		case 0x1B:
			return FALSE;		
		default:
			break;
	}

	FX_BOOL bCtrl = IsCTRLpressed(nFlag);
	FX_BOOL bAlt = IsALTpressed(nFlag);
	FX_BOOL bShift = IsSHIFTpressed(nFlag);

	FX_WORD word = nChar;

	if (bCtrl && !bAlt)
	{
		switch (nChar)
		{
			case 'C' - 'A' + 1:
				this->CopyText();
				return TRUE;
			case 'V' - 'A' + 1:
				this->PasteText();
				return TRUE;
			case 'X' - 'A' + 1:
				this->CutText();
				return TRUE;
			case 'A' - 'A' + 1:
				this->SelectAll();
				return TRUE;
			case 'Z' - 'A' + 1:
				if (bShift)
					Redo();
				else
					Undo();
				return TRUE;
			default:
				if (nChar < 32)
					return FALSE;
		}
	}

	if (IsReadOnly()) return TRUE;

	if (m_pEdit->IsSelected() && word ==  FWL_VKEY_Back)
		word = FWL_VKEY_Unknown;

	Clear();

	switch (word)
	{
	case FWL_VKEY_Back:
		Backspace();
		break;
	case FWL_VKEY_Return:	
		InsertReturn();
		break;
	case FWL_VKEY_Unknown:
		break;
	default:
		if (IsINSERTpressed(nFlag))
			Delete();
		InsertWord(word, this->GetCharSet());
		break;
	}

	return TRUE;
}

FX_BOOL CPWL_EditCtrl::OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnLButtonDown(point,nFlag);

	if (ClientHitTest(point))
	{		
		if (m_bMouseDown)
			this->InvalidateRect();

		m_bMouseDown = TRUE;		
		SetCapture();

		m_pEdit->OnMouseDown(point,IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
	}

	return TRUE;
}

FX_BOOL CPWL_EditCtrl::OnLButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnLButtonUp(point,nFlag);

	if (m_bMouseDown)
	{
		//can receive keybord message
		if (ClientHitTest(point) && !this->IsFocused())
			SetFocus();	

		ReleaseCapture();
		m_bMouseDown = FALSE;
	}

	return TRUE;
}

FX_BOOL CPWL_EditCtrl::OnMouseMove(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnMouseMove(point,nFlag);

	if (m_bMouseDown)
		m_pEdit->OnMouseMove(point,FALSE,FALSE);

	return TRUE;
}

CPDF_Rect CPWL_EditCtrl::GetContentRect() const
{
	return m_pEdit->GetContentRect();
}

void CPWL_EditCtrl::SetEditCaret(FX_BOOL bVisible)
{
	CPDF_Point ptHead(0,0),ptFoot(0,0);

	if (bVisible)
	{
		GetCaretInfo(ptHead,ptFoot);
	}

	CPVT_WordPlace wpTemp = m_pEdit->GetCaretWordPlace();
	this->IOnSetCaret(bVisible,ptHead,ptFoot,wpTemp);
}

void CPWL_EditCtrl::GetCaretInfo(CPDF_Point & ptHead, CPDF_Point & ptFoot) const
{
	if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())
	{
		pIterator->SetAt(m_pEdit->GetCaret());
		CPVT_Word word;
		CPVT_Line line;
		if (pIterator->GetWord(word))
		{
			ptHead.x = word.ptWord.x + word.fWidth;
			ptHead.y = word.ptWord.y + word.fAscent;
			ptFoot.x = word.ptWord.x + word.fWidth;
			ptFoot.y = word.ptWord.y + word.fDescent;
		}
		else if (pIterator->GetLine(line))
		{				
			ptHead.x = line.ptLine.x;
			ptHead.y = line.ptLine.y + line.fLineAscent;
			ptFoot.x = line.ptLine.x;
			ptFoot.y = line.ptLine.y + line.fLineDescent;
		}
	}
}

void CPWL_EditCtrl::GetCaretPos(FX_INT32& x, FX_INT32& y) const
{
	CPDF_Point ptHead(0,0), ptFoot(0,0);

	GetCaretInfo(ptHead,ptFoot);

	PWLtoWnd(ptHead, x, y);
}

void CPWL_EditCtrl::SetCaret(FX_BOOL bVisible, const CPDF_Point & ptHead, const CPDF_Point & ptFoot)
{
	if (m_pEditCaret)
	{
		if (!IsFocused() || m_pEdit->IsSelected())
			bVisible = FALSE;

		m_pEditCaret->SetCaret(bVisible, ptHead, ptFoot);
	}
}

FX_BOOL	CPWL_EditCtrl::IsModified() const
{
	return m_pEdit->IsModified();
}

CFX_WideString CPWL_EditCtrl::GetText() const
{
	return m_pEdit->GetText();
}

void CPWL_EditCtrl::SetSel(FX_INT32 nStartChar,FX_INT32 nEndChar)
{
	m_pEdit->SetSel(nStartChar, nEndChar);
}

void CPWL_EditCtrl::GetSel(FX_INT32 & nStartChar, FX_INT32 & nEndChar ) const
{
	m_pEdit->GetSel(nStartChar, nEndChar);
}

void CPWL_EditCtrl::Clear()
{
	if (!IsReadOnly())
		m_pEdit->Clear();
}

void CPWL_EditCtrl::SelectAll()
{
	m_pEdit->SelectAll();
}

void CPWL_EditCtrl::Paint()
{
	if (m_pEdit)
		m_pEdit->Paint();
}

void CPWL_EditCtrl::EnableRefresh(FX_BOOL bRefresh)
{
	if (m_pEdit)
		m_pEdit->EnableRefresh(bRefresh);
}

FX_INT32 CPWL_EditCtrl::GetCaret() const
{
	if (m_pEdit)
		return m_pEdit->GetCaret();

	return -1;
}

void CPWL_EditCtrl::SetCaret(FX_INT32 nPos)
{
	if (m_pEdit)
		m_pEdit->SetCaret(nPos);
}

FX_INT32 CPWL_EditCtrl::GetTotalWords() const
{
	if (m_pEdit)
		return m_pEdit->GetTotalWords();

	return 0;
}

void CPWL_EditCtrl::SetScrollPos(const CPDF_Point& point)
{
	if (m_pEdit)
		m_pEdit->SetScrollPos(point);
}

CPDF_Point CPWL_EditCtrl::GetScrollPos() const
{
	if (m_pEdit)
		return m_pEdit->GetScrollPos();

	return CPDF_Point(0.0f, 0.0f);
}

CPDF_Font * CPWL_EditCtrl::GetCaretFont() const
{
	FX_INT32 nFontIndex = 0;

	if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())
	{
		pIterator->SetAt(m_pEdit->GetCaret());
		CPVT_Word word;
		CPVT_Section section;
		if (pIterator->GetWord(word))
		{
			nFontIndex = word.nFontIndex;
		}
		else if (HasFlag(PES_RICH))
		{
			if (pIterator->GetSection(section))
			{				
				nFontIndex = section.WordProps.nFontIndex;
			}
		}
	}

	if (IFX_Edit_FontMap * pFontMap = GetFontMap())
		return pFontMap->GetPDFFont(nFontIndex);
	else
		return NULL;
}

FX_FLOAT CPWL_EditCtrl::GetCaretFontSize() const
{
	FX_FLOAT fFontSize = GetFontSize();

	if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())
	{
		pIterator->SetAt(m_pEdit->GetCaret());
		CPVT_Word word;
		CPVT_Section section;
		if (pIterator->GetWord(word))
		{
			fFontSize = word.fFontSize;
		}
		else if (HasFlag(PES_RICH))
		{
			if (pIterator->GetSection(section))
			{				
				fFontSize = section.WordProps.fFontSize;
			}
		}
	}

	return fFontSize;
}

void CPWL_EditCtrl::SetText(FX_LPCWSTR csText)
{
	m_pEdit->SetText(csText);
}

void CPWL_EditCtrl::CopyText()
{
}

void CPWL_EditCtrl::PasteText()
{
}

void CPWL_EditCtrl::CutText()
{
}

void CPWL_EditCtrl::ShowVScrollBar(FX_BOOL bShow)
{
}

void CPWL_EditCtrl::InsertText(FX_LPCWSTR csText)
{
	if (!IsReadOnly())
		m_pEdit->InsertText(csText);
}

void CPWL_EditCtrl::InsertWord(FX_WORD word, FX_INT32 nCharset)
{
	if (!IsReadOnly())
		m_pEdit->InsertWord(word, nCharset);
}

void CPWL_EditCtrl::InsertReturn()
{
	if (!IsReadOnly())
		m_pEdit->InsertReturn();
}

void CPWL_EditCtrl::Delete()
{
	if (!IsReadOnly())
		m_pEdit->Delete();
}

void CPWL_EditCtrl::Backspace()
{
	if (!IsReadOnly())
		m_pEdit->Backspace();
}

FX_BOOL	CPWL_EditCtrl::CanUndo() const
{
	return !IsReadOnly() && m_pEdit->CanUndo();
}

FX_BOOL	CPWL_EditCtrl::CanRedo() const
{
	return !IsReadOnly() && m_pEdit->CanRedo();
}

void CPWL_EditCtrl::Redo()
{
	if (CanRedo())
		m_pEdit->Redo();
}

void CPWL_EditCtrl::Undo()
{
	if (CanUndo())
		m_pEdit->Undo();
}

void CPWL_EditCtrl::IOnSetScrollInfoY(FX_FLOAT fPlateMin, FX_FLOAT fPlateMax, 
												FX_FLOAT fContentMin, FX_FLOAT fContentMax, 
												FX_FLOAT fSmallStep, FX_FLOAT fBigStep)
{
	PWL_SCROLL_INFO Info;

	Info.fPlateWidth = fPlateMax - fPlateMin;
	Info.fContentMin = fContentMin;
	Info.fContentMax = fContentMax;
	Info.fSmallStep = fSmallStep;
	Info.fBigStep = fBigStep;

	this->OnNotify(this,PNM_SETSCROLLINFO,SBT_VSCROLL,(FX_INTPTR)&Info);

//	PWL_TRACE("set scroll info:%f\n",fContentMax - fContentMin);

	if (IsFloatBigger(Info.fPlateWidth,Info.fContentMax-Info.fContentMin)
		|| IsFloatEqual(Info.fPlateWidth,Info.fContentMax-Info.fContentMin))
	{
		this->ShowVScrollBar(FALSE);		
	}
	else
	{
		this->ShowVScrollBar(TRUE);
	}
}

void CPWL_EditCtrl::IOnSetScrollPosY(FX_FLOAT fy)
{
//	PWL_TRACE("set scroll position:%f\n",fy);
	this->OnNotify(this,PNM_SETSCROLLPOS,SBT_VSCROLL,(FX_INTPTR)&fy);
}

void CPWL_EditCtrl::IOnSetCaret(FX_BOOL bVisible, const CPDF_Point & ptHead, const CPDF_Point & ptFoot, const CPVT_WordPlace& place)
{
	PWL_CARET_INFO cInfo;
	cInfo.bVisible = bVisible;
	cInfo.ptHead = ptHead;
	cInfo.ptFoot = ptFoot;

	this->OnNotify(this,PNM_SETCARETINFO,(FX_INTPTR)&cInfo,(FX_INTPTR)NULL);
}

void CPWL_EditCtrl::IOnCaretChange(const CPVT_SecProps & secProps, const CPVT_WordProps & wordProps)
{
}

void CPWL_EditCtrl::IOnContentChange(const CPDF_Rect& rcContent)
{
	if (this->IsValid())
	{
		if (m_pEditNotify)
		{
			m_pEditNotify->OnContentChange(rcContent);
		}
	}
}

void CPWL_EditCtrl::IOnInvalidateRect(CPDF_Rect * pRect)
{
	this->InvalidateRect(pRect);
}

FX_INT32 CPWL_EditCtrl::GetCharSet() const
{
	if (m_nCharSet < 0)
		return DEFAULT_CHARSET; 
	else
		return m_nCharSet;
}

void CPWL_EditCtrl::GetTextRange(const CPDF_Rect& rect, FX_INT32 & nStartChar, FX_INT32 & nEndChar) const
{
	nStartChar = m_pEdit->WordPlaceToWordIndex(m_pEdit->SearchWordPlace(CPDF_Point(rect.left, rect.top)));
	nEndChar = m_pEdit->WordPlaceToWordIndex(m_pEdit->SearchWordPlace(CPDF_Point(rect.right, rect.bottom)));
}

CFX_WideString CPWL_EditCtrl::GetText(FX_INT32 & nStartChar, FX_INT32 & nEndChar) const
{
	CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStartChar);
	CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEndChar);
	return m_pEdit->GetRangeText(CPVT_WordRange(wpStart, wpEnd));
}

void	CPWL_EditCtrl::SetReadyToInput()
{
	if (m_bMouseDown)
	{
		ReleaseCapture();
		m_bMouseDown = FALSE;
	}
}
