// 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_ListBox.h"
#include "../../include/pdfwindow/PWL_Utils.h"
#include "../../include/pdfwindow/PWL_ScrollBar.h"
#include "../../include/pdfwindow/PWL_EditCtrl.h"
#include "../../include/pdfwindow/PWL_Edit.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_List_Notify ----------------------- */

CPWL_List_Notify::CPWL_List_Notify(CPWL_ListBox* pList) : m_pList(pList)
{
	ASSERT(m_pList != NULL);
}

CPWL_List_Notify::~CPWL_List_Notify()
{
}

void CPWL_List_Notify::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;

	m_pList->OnNotify(m_pList,PNM_SETSCROLLINFO,SBT_VSCROLL,(FX_INTPTR)&Info);

	if (CPWL_ScrollBar * pScroll = m_pList->GetVScrollBar())
	{
		if (IsFloatBigger(Info.fPlateWidth,Info.fContentMax-Info.fContentMin)
			|| IsFloatEqual(Info.fPlateWidth,Info.fContentMax-Info.fContentMin))
		{
			if (pScroll->IsVisible())
			{
				pScroll->SetVisible(FALSE);
				m_pList->RePosChildWnd();
			}			
		}
		else
		{
			if (!pScroll->IsVisible())
			{
				pScroll->SetVisible(TRUE);	
				m_pList->RePosChildWnd();
			}
		}
	}	
}

void CPWL_List_Notify::IOnSetScrollPosY(FX_FLOAT fy)
{
	m_pList->OnNotify(m_pList,PNM_SETSCROLLPOS,SBT_VSCROLL,(FX_INTPTR)&fy);
}

void CPWL_List_Notify::IOnInvalidateRect(CPDF_Rect * pRect)
{
	m_pList->InvalidateRect(pRect);
}

/* --------------------------- CPWL_ListBox ---------------------------- */

CPWL_ListBox::CPWL_ListBox() :
	m_pList(NULL),
	m_pListNotify(NULL),
	m_bMouseDown(FALSE),
	m_bHoverSel(FALSE),
	m_pFillerNotify(NULL)
{
	m_pList = IFX_List::NewList();

	ASSERT(m_pList != NULL);
}

CPWL_ListBox::~CPWL_ListBox()
{
	IFX_List::DelList(m_pList);
	
	if (m_pListNotify)
	{
		delete m_pListNotify;
		m_pListNotify = NULL;
	}
}

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

void CPWL_ListBox::OnCreated()
{
	if (m_pList)
	{
		if (m_pListNotify) delete m_pListNotify;

		m_pList->SetFontMap(GetFontMap());
		m_pList->SetNotify(m_pListNotify = new CPWL_List_Notify(this));
	
		SetHoverSel(HasFlag(PLBS_HOVERSEL));	
		m_pList->SetMultipleSel(HasFlag(PLBS_MULTIPLESEL));
		m_pList->SetFontSize(this->GetCreationParam().fFontSize);	

		m_bHoverSel = HasFlag(PLBS_HOVERSEL);
	}
}

void CPWL_ListBox::OnDestroy()
{
	if (m_pListNotify)
	{
		delete m_pListNotify;
		m_pListNotify = NULL;
	}
}

void CPWL_ListBox::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
{
	CPWL_Wnd::GetThisAppearanceStream(sAppStream);

	CFX_ByteTextBuf sListItems;

	if (m_pList)
	{
		CPDF_Rect rcPlate = m_pList->GetPlateRect();
		for (FX_INT32 i=0,sz=m_pList->GetCount(); i<sz; i++)
		{
			CPDF_Rect rcItem = m_pList->GetItemRect(i);

			if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom) continue;
			
			CPDF_Point ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f);
			if (m_pList->IsItemSelected(i))
			{
				sListItems << CPWL_Utils::GetRectFillAppStream(rcItem,PWL_DEFAULT_SELBACKCOLOR);
				CFX_ByteString sItem = CPWL_Utils::GetEditAppStream(m_pList->GetItemEdit(i), ptOffset);
				if (sItem.GetLength() > 0)
				{
					sListItems << "BT\n" << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELTEXTCOLOR) << sItem << "ET\n";
				}
			}
			else
			{
				CFX_ByteString sItem = CPWL_Utils::GetEditAppStream(m_pList->GetItemEdit(i), ptOffset);
				if (sItem.GetLength() > 0)
				{
					sListItems << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sItem << "ET\n";
				}
			}
		}
	}

	if (sListItems.GetLength() > 0)
	{
		CFX_ByteTextBuf sClip;			
		CPDF_Rect rcClient = this->GetClientRect();

		sClip << "q\n";
		sClip << rcClient.left << " " << rcClient.bottom << " "
			<< rcClient.right - rcClient.left << " " <<	rcClient.top - rcClient.bottom << " re W n\n";

		sClip << sListItems << "Q\n";

		sAppStream << "/Tx BMC\n" << sClip << "EMC\n";
	}
}

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

	if (m_pList)
	{
		CPDF_Rect rcPlate = m_pList->GetPlateRect();
		CPDF_Rect rcList = GetListRect();
		CPDF_Rect rcClient = GetClientRect();

		for (FX_INT32 i=0,sz=m_pList->GetCount(); i<sz; i++)
		{
			CPDF_Rect rcItem = m_pList->GetItemRect(i);
			if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom) continue;
			
			CPDF_Point ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f);
			if (IFX_Edit* pEdit = m_pList->GetItemEdit(i))
			{
				CPDF_Rect rcContent = pEdit->GetContentRect();
				if (rcContent.Width() > rcClient.Width())
					rcItem.Intersect(rcList);
				else
					rcItem.Intersect(rcClient);
			}

			if (m_pList->IsItemSelected(i))
			{
			//	CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcItem, ArgbEncode(255,0,51,113));
				IFX_SystemHandler* pSysHandler = GetSystemHandler();
				if(pSysHandler && pSysHandler->IsSelectionImplemented())
				{
					IFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i), CPWL_Utils::PWLColorToFXColor(GetTextColor()), CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor()),
						rcList, ptOffset, NULL,pSysHandler, m_pFormFiller);
					pSysHandler->OutputSelectedRect(m_pFormFiller, rcItem);
				}
				else
				{
					CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcItem, ArgbEncode(255,0,51,113));
					IFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i), ArgbEncode(255,255,255,255), 0,
						rcList, ptOffset, NULL, pSysHandler, m_pFormFiller);
				}
			}
			else
			{
				IFX_SystemHandler* pSysHandler = GetSystemHandler();
				IFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i), 
						CPWL_Utils::PWLColorToFXColor(GetTextColor()),
						CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor()),
						rcList, ptOffset, NULL,pSysHandler, NULL);

			}
		}
	}
}

FX_BOOL CPWL_ListBox::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag)
{
	CPWL_Wnd::OnKeyDown(nChar, 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;
	}

	FX_BOOL bExit = FALSE;
	OnNotifySelChanged(TRUE,bExit,nFlag);

	return TRUE;
}

FX_BOOL CPWL_ListBox::OnChar(FX_WORD nChar, FX_DWORD nFlag)
{
	CPWL_Wnd::OnChar(nChar,nFlag);

	if (!m_pList) return FALSE;

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

	FX_BOOL bExit = FALSE;
	OnNotifySelChanged(TRUE,bExit, nFlag);

	return TRUE;
}

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

	if (ClientHitTest(point))
	{
		m_bMouseDown = TRUE;
		SetFocus();
		SetCapture();

		if (m_pList)
			m_pList->OnMouseDown(point,IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
	}

	return TRUE;
}

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

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

	FX_BOOL bExit = FALSE;
	OnNotifySelChanged(FALSE,bExit,nFlag);

	return TRUE;
}

void CPWL_ListBox::SetHoverSel(FX_BOOL bHoverSel)
{
	m_bHoverSel = bHoverSel;
}

FX_BOOL CPWL_ListBox::OnMouseMove(const CPDF_Point & point, FX_DWORD nFlag)
{
	CPWL_Wnd::OnMouseMove(point, nFlag);

	if (m_bHoverSel && !IsCaptureMouse() && ClientHitTest(point))
	{
		if (m_pList)
			m_pList->Select(m_pList->GetItemIndex(point));
	}

	if (m_bMouseDown)
	{
		if (m_pList)
			m_pList->OnMouseMove(point,IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
	}	

	return TRUE;
}

void CPWL_ListBox::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, FX_INTPTR wParam, FX_INTPTR lParam)
{
	CPWL_Wnd::OnNotify(pWnd,msg,wParam,lParam);

	FX_FLOAT fPos;	
	
	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:
		fPos = *(FX_FLOAT*)lParam;
		switch (wParam)
		{
		case SBT_VSCROLL:
			if (m_pList)
				m_pList->SetScrollPos(CPDF_Point(0,fPos));
			break;
		}
		break;
	}
}

void CPWL_ListBox::KillFocus()
{
	CPWL_Wnd::KillFocus();

	/*
	if (this->IsMultipleSel())
	{
		for(FX_INT32 i=0;i<this->GetCount();i++)
		{
			if (this->IsListItemSelected(i))
			{
				if (!IsListItemVisible(i))
					this->ScrollToListItem(i);
				break;
			}
		}
	}
	else
	{
		if (!IsListItemVisible(this->GetCurSel()))
			this->ScrollToListItem(this->GetCurSel());
	}

	SetListItemCaret(m_nCaretIndex,FALSE);
	*/
}

void CPWL_ListBox::RePosChildWnd()
{
	CPWL_Wnd::RePosChildWnd();

	if (m_pList)
		m_pList->SetPlateRect(GetListRect());
}

void CPWL_ListBox::OnNotifySelChanged(FX_BOOL bKeyDown, FX_BOOL & bExit,  FX_DWORD nFlag)
{
	if (m_pFillerNotify)
	{		
		FX_BOOL bRC = TRUE;
		CFX_WideString swChange = GetText();
		CFX_WideString strChangeEx;
		int nSelStart = 0;
		int nSelEnd = swChange.GetLength();
		m_pFillerNotify->OnBeforeKeyStroke(FALSE, GetAttachedData(), 0, swChange, strChangeEx, nSelStart, nSelEnd, bKeyDown, bRC, bExit, nFlag);
		if (bExit) return;

		m_pFillerNotify->OnAfterKeyStroke(FALSE, GetAttachedData(), bExit,nFlag);
	}
}

CPDF_Rect CPWL_ListBox::GetFocusRect() const
{
	if (m_pList && m_pList->IsMultipleSel())
	{
		CPDF_Rect rcCaret = m_pList->GetItemRect(m_pList->GetCaret());
		rcCaret.Intersect(GetClientRect());
		return rcCaret;
	}
	
	return CPWL_Wnd::GetFocusRect();
}

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

void CPWL_ListBox::SetText(FX_LPCWSTR csText,FX_BOOL bRefresh)
{
	//return CPDF_List::SetText(csText,bRefresh);
}

CFX_WideString CPWL_ListBox::GetText() const
{
	if (m_pList)
		return m_pList->GetText();

	return L"";
}

void CPWL_ListBox::SetFontSize(FX_FLOAT fFontSize)
{
	if (m_pList)
		m_pList->SetFontSize(fFontSize);
}

FX_FLOAT CPWL_ListBox::GetFontSize() const
{
	if (m_pList)
		return m_pList->GetFontSize();
	return 0.0f;
}

void CPWL_ListBox::Select(FX_INT32 nItemIndex)
{
	if (m_pList)
		m_pList->Select(nItemIndex);
}

void CPWL_ListBox::SetCaret(FX_INT32 nItemIndex)
{
	if (m_pList)
		m_pList->SetCaret(nItemIndex);
}

void CPWL_ListBox::SetTopVisibleIndex(FX_INT32 nItemIndex)
{
	if (m_pList)
		m_pList->SetTopItem(nItemIndex);
}

void CPWL_ListBox::ScrollToListItem(FX_INT32 nItemIndex)
{
	if (m_pList)
		m_pList->ScrollToListItem(nItemIndex);
}

void CPWL_ListBox::ResetContent()
{
	if (m_pList)
		m_pList->Empty();
}

void CPWL_ListBox::Reset()
{
	if (m_pList)
		m_pList->Cancel();
}

FX_BOOL CPWL_ListBox::IsMultipleSel() const
{
	if (m_pList)
		return m_pList->IsMultipleSel();

	return FALSE;
}

FX_INT32 CPWL_ListBox::GetCaretIndex() const
{
	if (m_pList)
		return m_pList->GetCaret();

	return -1;
}

FX_INT32 CPWL_ListBox::GetCurSel() const
{
	if (m_pList)
		return m_pList->GetSelect();

	return -1;
}

FX_BOOL CPWL_ListBox::IsItemSelected(FX_INT32 nItemIndex) const
{
	if (m_pList)
		return m_pList->IsItemSelected(nItemIndex);

	return FALSE;
}

FX_INT32 CPWL_ListBox::GetTopVisibleIndex() const
{
	if (m_pList)
	{
		m_pList->ScrollToListItem(m_pList->GetFirstSelected());
		return m_pList->GetTopItem();
	}

	return -1;
}

FX_INT32 CPWL_ListBox::GetCount() const
{
	if (m_pList)
		return m_pList->GetCount();

	return 0;
}

FX_INT32 CPWL_ListBox::FindNext(FX_INT32 nIndex,FX_WCHAR nChar) const
{
	if (m_pList)
		return m_pList->FindNext(nIndex,nChar);

	return nIndex;
}

CPDF_Rect CPWL_ListBox::GetContentRect() const
{
	if (m_pList)
		return m_pList->GetContentRect();

	return CPDF_Rect();
}

FX_FLOAT CPWL_ListBox::GetFirstHeight() const
{
	if (m_pList)
		return m_pList->GetFirstHeight();

	return 0.0f;
}

CPDF_Rect CPWL_ListBox::GetListRect() const
{
	return CPWL_Utils::DeflateRect(GetWindowRect(),(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));
}

FX_BOOL	CPWL_ListBox::OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag)
{
	if (!m_pList) return FALSE;

	if (zDelta < 0)
	{
		m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
	}
	else
	{
		m_pList->OnVK_UP(IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));
	}

	FX_BOOL bExit = FALSE;
	OnNotifySelChanged(FALSE,bExit, nFlag);
	return TRUE;
}

