// 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_Edit.h"
#include "../../include/pdfwindow/PWL_ListBox.h"
#include "../../include/pdfwindow/PWL_ComboBox.h"
#include "../../include/pdfwindow/PWL_Utils.h"

#define PWLCB_DEFAULTFONTSIZE  12.0f

#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_CBListBox ---------------------------- */

FX_BOOL	CPWL_CBListBox::OnLButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnLButtonUp(point,nFlag);

	if (m_bMouseDown)
	{
		ReleaseCapture();
		m_bMouseDown = FALSE;	

		if (this->ClientHitTest(point))
		{
			if (CPWL_Wnd * pParent = GetParentWindow())
			{
				pParent->OnNotify(this,PNM_LBUTTONUP,0,PWL_MAKEDWORD(point.x,point.y));			
			}
		
			FX_BOOL bExit = FALSE;
			OnNotifySelChanged(FALSE,bExit, nFlag);
			if (bExit) return FALSE;
		}
	}

	return TRUE;
}

FX_BOOL CPWL_CBListBox::OnKeyDown(FX_WORD nChar, FX_BOOL & bExit, FX_DWORD nFlag)
{
	if (!m_pList) return FALSE;

	switch (nChar)
	{
	default:
		return FALSE;
	case FWL_VKEY_Up:
	case FWL_VKEY_Down:
	case FWL_VKEY_Home:
	case FWL_VKEY_Left:
	case FWL_VKEY_End:
	case FWL_VKEY_Right:
		break;	
	}

	switch (nChar)
	{
	case FWL_VKEY_Up:
		m_pList->OnVK_UP(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
		break;
	case FWL_VKEY_Down:
		m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
		break;
	case FWL_VKEY_Home:
		m_pList->OnVK_HOME(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
		break;
	case FWL_VKEY_Left:
		m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
		break;
	case FWL_VKEY_End:
		m_pList->OnVK_END(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
		break;
	case FWL_VKEY_Right:
		m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
		break;
	case FWL_VKEY_Delete:
		break;
	}

	OnNotifySelChanged(TRUE,bExit, nFlag);

	return TRUE;
}

FX_BOOL	CPWL_CBListBox::OnChar(FX_WORD nChar, FX_BOOL & bExit, FX_DWORD nFlag)
{
	if (!m_pList) return FALSE;

	if (!m_pList->OnChar(nChar,IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag))) return FALSE;

	if (CPWL_ComboBox* pComboBox = (CPWL_ComboBox*)GetParentWindow())
	{
		pComboBox->SetSelectText();
	}

	OnNotifySelChanged(TRUE,bExit,nFlag);

	return TRUE;
}

/* ---------------------------- CPWL_CBButton ---------------------------- */

void CPWL_CBButton::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
	CPWL_Wnd::GetThisAppearanceStream(sAppStream);
	
	CPDF_Rect rectWnd = CPWL_Wnd::GetWindowRect();
	
	if (IsVisible() && !rectWnd.IsEmpty())
	{
		CFX_ByteTextBuf sButton;	

		CPDF_Point ptCenter = this->GetCenterPoint();

		CPDF_Point pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN,ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
		CPDF_Point pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN,ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
		CPDF_Point pt3(ptCenter.x,ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);

		if (IsFloatBigger(rectWnd.right - rectWnd.left,PWL_CBBUTTON_TRIANGLE_HALFLEN * 2)
			&&
			IsFloatBigger(rectWnd.top - rectWnd.bottom,PWL_CBBUTTON_TRIANGLE_HALFLEN)
			)
		{
			sButton << "0 g\n";
			sButton << pt1.x << " " << pt1.y << " m\n";
			sButton << pt2.x << " " << pt2.y << " l\n";
			sButton << pt3.x << " " << pt3.y << " l\n";
			sButton << pt1.x << " " << pt1.y << " l f\n";

			sAppStream << "q\n" << sButton << "Q\n";
		}	
	}
}

void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	CPWL_Wnd::DrawThisAppearance(pDevice,pUser2Device);

	CPDF_Rect rectWnd = CPWL_Wnd::GetWindowRect();
	
	if (IsVisible() && !rectWnd.IsEmpty())
	{
		CPDF_Point ptCenter = this->GetCenterPoint();

		CPDF_Point pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN,ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
		CPDF_Point pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN,ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
		CPDF_Point pt3(ptCenter.x,ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);

		if (IsFloatBigger(rectWnd.right - rectWnd.left,PWL_CBBUTTON_TRIANGLE_HALFLEN * 2)
			&&
			IsFloatBigger(rectWnd.top - rectWnd.bottom,PWL_CBBUTTON_TRIANGLE_HALFLEN)
			)
		{
			CFX_PathData path;

			path.SetPointCount(4);
			path.SetPoint(0, pt1.x, pt1.y, FXPT_MOVETO);
			path.SetPoint(1, pt2.x, pt2.y, FXPT_LINETO);
			path.SetPoint(2, pt3.x, pt3.y, FXPT_LINETO);
			path.SetPoint(3, pt1.x, pt1.y, FXPT_LINETO);

			pDevice->DrawPath(&path, pUser2Device, NULL, 
				CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_BLACKCOLOR,GetTransparency()), 
				0, FXFILL_ALTERNATE);
		}
	}
}

FX_BOOL	CPWL_CBButton::OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnLButtonDown(point,nFlag);

	SetCapture();

	if (CPWL_Wnd * pParent = GetParentWindow())
	{		
		pParent->OnNotify(this,PNM_LBUTTONDOWN,0,PWL_MAKEDWORD(point.x,point.y));
	}
	
	return TRUE;
}

FX_BOOL	CPWL_CBButton::OnLButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnLButtonUp(point, nFlag);

	ReleaseCapture();

	return TRUE;
}

/* ---------------------------- CPWL_ComboBox ---------------------------- */

CPWL_ComboBox::CPWL_ComboBox() : m_pEdit(NULL),
	m_pButton(NULL),
	m_pList(NULL),
	m_bPopup(FALSE),
	m_nPopupWhere(0),
	m_nSelectItem(-1),
	m_pFillerNotify(NULL)
{
}

CFX_ByteString CPWL_ComboBox::GetClassName() const
{
	return "CPWL_ComboBox";
}

void CPWL_ComboBox::OnCreate(PWL_CREATEPARAM & cp)
{
	cp.dwFlags &= ~PWS_HSCROLL;
	cp.dwFlags &= ~PWS_VSCROLL;
}

void CPWL_ComboBox::SetFocus()
{
	if (m_pEdit)
		m_pEdit->SetFocus();
}

void CPWL_ComboBox::KillFocus()
{
	SetPopup(FALSE);
	CPWL_Wnd::KillFocus();
}

CFX_WideString CPWL_ComboBox::GetText() const
{
	if (m_pEdit)
	{
		return m_pEdit->GetText();
	}
	return CFX_WideString();
}

void CPWL_ComboBox::SetText(FX_LPCWSTR text)
{
	if (m_pEdit)
		m_pEdit->SetText(text);
}

void CPWL_ComboBox::AddString(FX_LPCWSTR string)
{
	if (m_pList)
		m_pList->AddString(string);
}

FX_INT32 CPWL_ComboBox::GetSelect() const
{
	return m_nSelectItem;
}

void CPWL_ComboBox::SetSelect(FX_INT32 nItemIndex)
{
	if (m_pList)
		m_pList->Select(nItemIndex);

	m_pEdit->SetText(m_pList->GetText());

	m_nSelectItem = nItemIndex;
}

void CPWL_ComboBox::SetEditSel(FX_INT32 nStartChar,FX_INT32 nEndChar)
{
	if (m_pEdit)
	{
		m_pEdit->SetSel(nStartChar,nEndChar);
	}
}

void CPWL_ComboBox::GetEditSel(FX_INT32 & nStartChar, FX_INT32 & nEndChar) const
{
	nStartChar = -1;
	nEndChar = -1;

	if (m_pEdit)
	{
		m_pEdit->GetSel(nStartChar,nEndChar);
	}
}

void CPWL_ComboBox::Clear()
{
	if (m_pEdit)
	{
		m_pEdit->Clear();
	}
}

void CPWL_ComboBox::CreateChildWnd(const PWL_CREATEPARAM & cp)
{
	CreateEdit(cp);
	CreateButton(cp);
	CreateListBox(cp);
}

void CPWL_ComboBox::CreateEdit(const PWL_CREATEPARAM & cp)
{
	if (!m_pEdit)
	{
		m_pEdit = new CPWL_CBEdit;
		m_pEdit->AttachFFLData(m_pFormFiller);

		PWL_CREATEPARAM ecp = cp;
		ecp.pParentWnd = this;
		ecp.dwFlags =  PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER | PES_AUTOSCROLL | PES_UNDO;

		if (HasFlag(PWS_AUTOFONTSIZE))
			ecp.dwFlags |= PWS_AUTOFONTSIZE;

		if (!HasFlag(PCBS_ALLOWCUSTOMTEXT))
			ecp.dwFlags |= PWS_READONLY;

		ecp.rcRectWnd = CPDF_Rect(0,0,0,0);
		ecp.dwBorderWidth = 0;
		ecp.nBorderStyle = PBS_SOLID;

		m_pEdit->Create(ecp);
	}
}

void CPWL_ComboBox::CreateButton(const PWL_CREATEPARAM & cp)
{
	if (!m_pButton)
	{
		m_pButton = new CPWL_CBButton;	

		PWL_CREATEPARAM bcp = cp;
		bcp.pParentWnd = this;
		bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND;	
		bcp.sBackgroundColor = PWL_SCROLLBAR_BKCOLOR;
		bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
		bcp.dwBorderWidth = 2;
		bcp.nBorderStyle = PBS_BEVELED;
		bcp.eCursorType = FXCT_ARROW;

		m_pButton->Create(bcp);
	}
}

void CPWL_ComboBox::CreateListBox(const PWL_CREATEPARAM & cp)
{
	if (!m_pList)
	{
		m_pList = new CPWL_CBListBox;
		m_pList->AttachFFLData(m_pFormFiller);
		PWL_CREATEPARAM lcp = cp;
		lcp.pParentWnd = this;
		lcp.dwFlags = PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL;
		lcp.nBorderStyle = PBS_SOLID;
		lcp.dwBorderWidth = 1;
		lcp.eCursorType = FXCT_ARROW;
		lcp.rcRectWnd = CPDF_Rect(0,0,0,0);

		if (cp.dwFlags & PWS_AUTOFONTSIZE)
			lcp.fFontSize = PWLCB_DEFAULTFONTSIZE;
		else
			lcp.fFontSize = cp.fFontSize;

		if (cp.sBorderColor.nColorType == COLORTYPE_TRANSPARENT)
			lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;

		if (cp.sBackgroundColor.nColorType == COLORTYPE_TRANSPARENT)
			lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;		

		m_pList->Create(lcp);
	}
}

void CPWL_ComboBox::RePosChildWnd()
{
	CPDF_Rect rcClient = GetClientRect();

	if (m_bPopup)
	{
		CPDF_Rect rclient = GetClientRect();
		CPDF_Rect rcButton = rclient;
		CPDF_Rect rcEdit = rcClient;
		CPDF_Rect rcList = CPWL_Wnd::GetWindowRect();

		FX_FLOAT fOldWindowHeight = m_rcOldWindow.Height();
		FX_FLOAT fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2;
		
		switch (m_nPopupWhere)
		{
		case 0:
			rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;

			if (rcButton.left < rclient.left)
				rcButton.left = rclient.left;
			
			rcButton.bottom = rcButton.top - fOldClientHeight;

			rcEdit.right = rcButton.left - 1.0f;

			if (rcEdit.left < rclient.left)
				rcEdit.left = rclient.left;

			if (rcEdit.right < rcEdit.left)
				rcEdit.right = rcEdit.left;

			rcEdit.bottom = rcEdit.top - fOldClientHeight;

			rcList.top -= fOldWindowHeight;

			break;
		case 1:
			rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;

			if (rcButton.left < rclient.left)
				rcButton.left = rclient.left;
			
			rcButton.top = rcButton.bottom + fOldClientHeight;

			rcEdit.right = rcButton.left - 1.0f;

			if (rcEdit.left < rclient.left)
				rcEdit.left = rclient.left;

			if (rcEdit.right < rcEdit.left)
				rcEdit.right = rcEdit.left;

			rcEdit.top = rcEdit.bottom + fOldClientHeight;

			rcList.bottom += fOldWindowHeight;

			break;
		}		

		if (m_pButton)
			m_pButton->Move(rcButton,TRUE,FALSE);

		if (m_pEdit)
			m_pEdit->Move(rcEdit,TRUE,FALSE);

		if (m_pList)
		{
			m_pList->SetVisible(TRUE);			
			m_pList->Move(rcList,TRUE,FALSE);
			m_pList->ScrollToListItem(m_nSelectItem);
		}
	}
	else
	{		
		CPDF_Rect rcButton = rcClient;

		rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;	
		
		if (rcButton.left < rcClient.left)
			rcButton.left = rcClient.left;

		if (m_pButton)
			m_pButton->Move(rcButton,TRUE,FALSE);

		CPDF_Rect rcEdit = rcClient;
		rcEdit.right = rcButton.left - 1.0f;

		if (rcEdit.left < rcClient.left)
			rcEdit.left = rcClient.left;

		if (rcEdit.right < rcEdit.left)
			rcEdit.right = rcEdit.left;

		if (m_pEdit)
			m_pEdit->Move(rcEdit,TRUE,FALSE);

		if (m_pList)
			m_pList->SetVisible(FALSE);
	}
}

void CPWL_ComboBox::SelectAll()
{
	if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT))
		m_pEdit->SelectAll();
}

CPDF_Rect CPWL_ComboBox::GetFocusRect() const
{
	return CPDF_Rect();
}

void CPWL_ComboBox::SetPopup(FX_BOOL bPopup)
{
	if (!m_pList) return;
	if (bPopup == m_bPopup) return;
	FX_FLOAT fListHeight = m_pList->GetContentRect().Height();
	if (!IsFloatBigger(fListHeight,0.0f)) return;

	if (bPopup)
	{
		if (m_pFillerNotify)
		{
			FX_INT32 nWhere = 0;
			FX_FLOAT fPopupRet = 0.0f;
			FX_FLOAT fPopupMin = 0.0f;
			if (m_pList->GetCount() > 3)
				fPopupMin = m_pList->GetFirstHeight() * 3 + m_pList->GetBorderWidth() * 2;
			FX_FLOAT fPopupMax = fListHeight + m_pList->GetBorderWidth() * 2;
			m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin,fPopupMax,nWhere,fPopupRet);

			if (IsFloatBigger(fPopupRet,0.0f))
			{
				m_bPopup = bPopup;

				CPDF_Rect rcWindow = CPWL_Wnd::GetWindowRect();
				m_rcOldWindow = rcWindow;
				switch (nWhere)
				{
				default:
				case 0:
					rcWindow.bottom -= fPopupRet;
					break;
				case 1:
					rcWindow.top += fPopupRet;
					break;
				}
				
				m_nPopupWhere = nWhere;
				Move(rcWindow, TRUE, TRUE);
			}
		}
	}
	else
	{
		m_bPopup = bPopup;
		Move(m_rcOldWindow, TRUE, TRUE);
	}
}

FX_BOOL CPWL_ComboBox::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag)
{
	if (!m_pList) return FALSE;
	if (!m_pEdit) return FALSE;

	m_nSelectItem = -1;

	switch (nChar)
	{
	case FWL_VKEY_Up:
		if (m_pList->GetCurSel() > 0)
		{
			FX_BOOL bExit = FALSE;
			if (m_pList->OnKeyDown(nChar,bExit,nFlag))
			{
				if (bExit) return FALSE;
				SetSelectText();				
			}
		}
		return TRUE;
	case FWL_VKEY_Down:
		if (m_pList->GetCurSel() < m_pList->GetCount() - 1)
		{
			FX_BOOL bExit = FALSE;
			if (m_pList->OnKeyDown(nChar,bExit,nFlag))
			{
				if (bExit) return FALSE;
				SetSelectText();				
			}
		}
		return TRUE;
	}

	if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
		return m_pEdit->OnKeyDown(nChar,nFlag);
	else
		return FALSE;
}

FX_BOOL CPWL_ComboBox::OnChar(FX_WORD nChar, FX_DWORD nFlag)
{
	if (!m_pList) return FALSE;
	if (!m_pEdit) return FALSE;

	m_nSelectItem = -1;
	FX_BOOL bExit = FALSE;

	if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
	{
		return m_pEdit->OnChar(nChar,nFlag);			
	}
	else
	{
		if (m_pList->OnChar(nChar,bExit,nFlag))
		{
			return bExit;
		}
		else
			return FALSE;
	}
}

void CPWL_ComboBox::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, FX_INTPTR wParam, FX_INTPTR lParam)
{
	switch (msg)
	{
	case PNM_LBUTTONDOWN:
		if (pWnd == m_pButton)
		{
			SetPopup(!m_bPopup);
			return;
		}
		break;
	case PNM_LBUTTONUP:
		if (m_pEdit && m_pList)
		{
			if (pWnd == m_pList)
			{			
				SetSelectText();
				SelectAll();
				m_pEdit->SetFocus();
				SetPopup(FALSE);
				return;
			}
		}
	}

	CPWL_Wnd::OnNotify(pWnd,msg,wParam,lParam);
}

FX_BOOL CPWL_ComboBox::IsPopup() const
{
	return m_bPopup;
}

void CPWL_ComboBox::SetSelectText()
{
	CFX_WideString swText = m_pList->GetText();
	m_pEdit->SelectAll();
	m_pEdit->ReplaceSel(m_pList->GetText());
	m_pEdit->SelectAll();

	m_nSelectItem = m_pList->GetCurSel();
}

FX_BOOL CPWL_ComboBox::IsModified() const
{
	return m_pEdit->IsModified();
}

void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify)
{
	 m_pFillerNotify = pNotify;

	 if (m_pEdit)
		 m_pEdit->SetFillerNotify(pNotify);

	 if (m_pList)
		 m_pList->SetFillerNotify(pNotify);
}

