// 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_ListCtrl.h"
#include "../../include/pdfwindow/PWL_IconList.h"
#include "../../include/pdfwindow/PWL_Utils.h"
#include "../../include/pdfwindow/PWL_ScrollBar.h"
#include "../../include/pdfwindow/PWL_Label.h"

#define PWL_IconList_ITEM_ICON_LEFTMARGIN		10.0f
#define PWL_IconList_ITEM_WIDTH					20.0f
#define PWL_IconList_ITEM_HEIGHT				20.0f
#define PWL_IconList_ITEM_SPACE					4.0f

/* ------------------ CPWL_IconList_Item ------------------- */

CPWL_IconList_Item::CPWL_IconList_Item() : 
	m_nIconIndex(-1), 
	m_pData(NULL),
	m_bSelected(FALSE),
	m_pText(NULL)
{
}

CPWL_IconList_Item::~CPWL_IconList_Item()
{
}

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

FX_FLOAT CPWL_IconList_Item::GetItemHeight(FX_FLOAT fLimitWidth)
{
	return PWL_IconList_ITEM_HEIGHT;
}

void CPWL_IconList_Item::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
{
	CPDF_Rect rcClient = GetClientRect();

	if (m_bSelected)
	{
		if (this->IsEnabled())
		{
			CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, 
				CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_SELBACKCOLOR,this->GetTransparency()));
		}
		else
		{
			CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, 
				CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_LIGHTGRAYCOLOR,this->GetTransparency()));
		}
	}

	CPDF_Rect rcIcon = rcClient;
	rcIcon.left += PWL_IconList_ITEM_ICON_LEFTMARGIN;
	rcIcon.right = rcIcon.left + PWL_IconList_ITEM_WIDTH;

	CPWL_Utils::DrawIconAppStream(pDevice, pUser2Device, m_nIconIndex, rcIcon, 
		m_crIcon, m_pText->GetTextColor(), this->GetTransparency());
}

void CPWL_IconList_Item::SetSelect(FX_BOOL bSelected)
{
	m_bSelected = bSelected;

	if (bSelected)
		m_pText->SetTextColor(PWL_DEFAULT_WHITECOLOR);
	else
		m_pText->SetTextColor(PWL_DEFAULT_BLACKCOLOR);

}

FX_BOOL	CPWL_IconList_Item::IsSelected() const
{
	return m_bSelected;
}

void CPWL_IconList_Item::CreateChildWnd(const PWL_CREATEPARAM & cp)
{
	m_pText = new CPWL_Label;

	PWL_CREATEPARAM lcp = cp;
	lcp.pParentWnd = this;
	lcp.dwFlags = PWS_CHILD | PWS_VISIBLE | PES_LEFT | PES_CENTER;
	lcp.sTextColor = PWL_DEFAULT_BLACKCOLOR;
	lcp.fFontSize = 12;
	m_pText->Create(lcp);
}

void CPWL_IconList_Item::SetData(void* pData)
{
	m_pData = pData;
}

void CPWL_IconList_Item::SetIcon(FX_INT32 nIconIndex)
{
	m_nIconIndex = nIconIndex;
}

void CPWL_IconList_Item::SetText(const CFX_WideString& str)
{
	m_pText->SetText(str);
}

CFX_WideString CPWL_IconList_Item::GetText() const
{
	return m_pText->GetText();
}

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

	rcClient.left += (PWL_IconList_ITEM_ICON_LEFTMARGIN + PWL_IconList_ITEM_WIDTH + PWL_IconList_ITEM_ICON_LEFTMARGIN);

	m_pText->Move(rcClient, TRUE, FALSE);
}

void CPWL_IconList_Item::SetIconFillColor(const CPWL_Color& color)
{
	m_crIcon = color;
}

void CPWL_IconList_Item::OnEnabled()
{
	if (m_bSelected)
		m_pText->SetTextColor(PWL_DEFAULT_WHITECOLOR);
	else
		m_pText->SetTextColor(PWL_DEFAULT_BLACKCOLOR);

	this->InvalidateRect();
}

void CPWL_IconList_Item::OnDisabled()
{
	m_pText->SetTextColor(PWL_DEFAULT_HEAVYGRAYCOLOR);

	this->InvalidateRect();
}

/* ----------------- CPWL_IconList_Content ----------------- */

CPWL_IconList_Content::CPWL_IconList_Content(FX_INT32 nListCount) : 
	m_nSelectIndex(-1),
	m_pNotify(NULL),
	m_bEnableNotify(TRUE),
	m_bMouseDown(FALSE),
	m_nListCount(nListCount)
{
}

CPWL_IconList_Content::~CPWL_IconList_Content()
{
}

void CPWL_IconList_Content::CreateChildWnd(const PWL_CREATEPARAM & cp)
{
	for (FX_INT32 i=0; i<m_nListCount; i++)
	{
		CPWL_IconList_Item* pNewItem = new CPWL_IconList_Item();

		PWL_CREATEPARAM icp = cp;
		icp.pParentWnd = this;
		icp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_NOREFRESHCLIP;
		pNewItem->Create(icp);
	}

	this->SetItemSpace(PWL_IconList_ITEM_SPACE);
	this->ResetContent(0);

	if (CPWL_Wnd * pParent = this->GetParentWindow())
	{
		CPDF_Rect rcScroll = this->GetScrollArea();
		this->GetScrollPos();

		PWL_SCROLL_INFO sInfo;
		sInfo.fContentMin = rcScroll.bottom;
		sInfo.fContentMax = rcScroll.top;
		sInfo.fPlateWidth = GetClientRect().Height();
		sInfo.fSmallStep = 13.0f;
		sInfo.fBigStep = sInfo.fPlateWidth;

		pParent->OnNotify(this, PNM_SETSCROLLINFO, SBT_VSCROLL, (FX_INTPTR)&sInfo);
	}
}

FX_BOOL	CPWL_IconList_Content::OnLButtonDown(const CPDF_Point & point)
{
	SetFocus();

	SetCapture();
	m_bMouseDown = TRUE;

	FX_INT32 nItemIndex = FindItemIndex(point);
	SetSelect(nItemIndex);
	ScrollToItem(nItemIndex);

	return TRUE;
}

FX_BOOL	CPWL_IconList_Content::OnLButtonUp(const CPDF_Point & point)
{
	m_bMouseDown = FALSE;
	ReleaseCapture();

	return TRUE;
}

FX_BOOL CPWL_IconList_Content::OnMouseMove(const CPDF_Point & point)
{
	if (m_bMouseDown)
	{
		FX_INT32 nItemIndex = FindItemIndex(point);
		SetSelect(nItemIndex);
		ScrollToItem(nItemIndex);
	}

	return TRUE;
}

FX_BOOL	CPWL_IconList_Content::OnKeyDown(FX_WORD nChar)
{
	switch (nChar)
	{
	case FWL_VKEY_Up:
		if (m_nSelectIndex > 0)
		{
			FX_INT32 nItemIndex = m_nSelectIndex - 1;
			SetSelect(nItemIndex);
			ScrollToItem(nItemIndex);
		}
		return TRUE;
	case FWL_VKEY_Down:
		if (m_nSelectIndex < m_nListCount-1)
		{
			FX_INT32 nItemIndex = m_nSelectIndex + 1;
			SetSelect(nItemIndex);
			ScrollToItem(nItemIndex);
		}
		return TRUE;
	}

	return FALSE;
}

FX_INT32 CPWL_IconList_Content::FindItemIndex(const CPDF_Point& point)
{
	FX_INT32 nIndex = 0;
	for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
	{
		if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
		{
			CPDF_Rect rcWnd = pChild->ChildToParent(pChild->GetWindowRect());

			if (point.y < rcWnd.top)
			{
				nIndex = i;
			}
		}
	}

	return nIndex;
}

void CPWL_IconList_Content::ScrollToItem(FX_INT32 nItemIndex)
{
	CPDF_Rect rcClient = GetClientRect();

	if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
	{
		CPDF_Rect rcOrigin = pItem->GetWindowRect();
		CPDF_Rect rcWnd = pItem->ChildToParent(rcOrigin);

		if (!(rcWnd.bottom > rcClient.bottom && rcWnd.top < rcClient.top))
		{
			CPDF_Point ptScroll = GetScrollPos();

			if (rcWnd.top > rcClient.top)
			{
				ptScroll.y = rcOrigin.top;
			}
			else if (rcWnd.bottom < rcClient.bottom)
			{
				ptScroll.y = rcOrigin.bottom + rcClient.Height();					
			}

			this->SetScrollPos(ptScroll);
			this->ResetFace();
			this->InvalidateRect();
			if (CPWL_Wnd* pParent = this->GetParentWindow())
			{
				pParent->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptScroll.y);
			}
		}
	}
}

void CPWL_IconList_Content::SetSelect(FX_INT32 nIndex)
{
	if (m_nSelectIndex != nIndex)
	{
		SelectItem(m_nSelectIndex, FALSE);
		SelectItem(nIndex, TRUE);
		m_nSelectIndex = nIndex;

		if (IPWL_IconList_Notify* pNotify = GetNotify())
			pNotify->OnNoteListSelChanged(nIndex);
	}
}

FX_INT32 CPWL_IconList_Content::GetSelect() const
{
	return m_nSelectIndex;
}

IPWL_IconList_Notify* CPWL_IconList_Content::GetNotify() const
{
	if (m_bEnableNotify)
		return m_pNotify;
	return NULL;
}

void CPWL_IconList_Content::SetNotify(IPWL_IconList_Notify* pNotify)
{
	m_pNotify = pNotify;
}

void CPWL_IconList_Content::EnableNotify(FX_BOOL bNotify)
{
	m_bEnableNotify = bNotify;
}

void CPWL_IconList_Content::SelectItem(FX_INT32 nItemIndex, FX_BOOL bSelect)
{
	if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
	{
		pItem->SetSelect(bSelect);
		pItem->InvalidateRect();		
	}
}

CPWL_IconList_Item* CPWL_IconList_Content::GetListItem(FX_INT32 nItemIndex) const
{
	if (nItemIndex >= 0 && nItemIndex<m_aChildren.GetSize())
	{
		if (CPWL_Wnd * pChild = m_aChildren.GetAt(nItemIndex))
		{
			if (pChild->GetClassName() == "CPWL_IconList_Item")
			{
				return (CPWL_IconList_Item*)pChild;
			}
		}
	}

	return NULL;
}

void CPWL_IconList_Content::SetListData(FX_INT32 nItemIndex, void* pData)
{
	if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
		pItem->SetData(pData);
}

void CPWL_IconList_Content::SetListIcon(FX_INT32 nItemIndex, FX_INT32 nIconIndex)
{
	if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
		pItem->SetIcon(nIconIndex);
}

void CPWL_IconList_Content::SetListString(FX_INT32 nItemIndex, const CFX_WideString& str)
{
	if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
		pItem->SetText(str);
}

CFX_WideString CPWL_IconList_Content::GetListString(FX_INT32 nItemIndex) const
{
	if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
		return pItem->GetText();

	return L"";
}

void CPWL_IconList_Content::SetIconFillColor(const CPWL_Color& color)
{
	for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++)
	{
		if (CPWL_Wnd * pChild = m_aChildren.GetAt(i))
		{
			if (pChild->GetClassName() == "CPWL_IconList_Item")
			{
				CPWL_IconList_Item* pItem = (CPWL_IconList_Item*)pChild;
				pItem->SetIconFillColor(color);
				pItem->InvalidateRect();
			}
		}
	}

}

/* -------------------- CPWL_IconList --------------------- */

CPWL_IconList::CPWL_IconList(FX_INT32 nListCount) : 
	m_pListContent(NULL),
	m_nListCount(nListCount)
{
}

CPWL_IconList::~CPWL_IconList()
{
}

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

	if (m_pListContent)
		m_pListContent->Move(GetClientRect(), TRUE, FALSE);
}

void CPWL_IconList::CreateChildWnd(const PWL_CREATEPARAM & cp)
{
	m_pListContent = new CPWL_IconList_Content(m_nListCount);

	PWL_CREATEPARAM ccp = cp;
	ccp.pParentWnd = this;
	ccp.dwFlags = PWS_CHILD | PWS_VISIBLE;
	m_pListContent->Create(ccp);
}

void CPWL_IconList::OnCreated()
{
	if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar())
	{
		pScrollBar->RemoveFlag(PWS_AUTOTRANSPARENT);
		pScrollBar->SetTransparency(255);
		pScrollBar->SetNotifyForever(TRUE);
	}
}

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

	if (wParam == SBT_VSCROLL)
	{		
		switch (msg)
		{
		case PNM_SETSCROLLINFO:
			if (PWL_SCROLL_INFO* pInfo = (PWL_SCROLL_INFO*)lParam)
			{
				if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar())
				{
					if (pInfo->fContentMax - pInfo->fContentMin > pInfo->fPlateWidth)
					{
						if (!pScrollBar->IsVisible())
						{
							pScrollBar->SetVisible(TRUE);
							RePosChildWnd();			
						}
						else
						{
						}
					}
					else
					{
						if (pScrollBar->IsVisible())
						{
							pScrollBar->SetVisible(FALSE);
							RePosChildWnd();
						}

						if (m_pListContent)
							m_pListContent->SetScrollPos(CPDF_Point(0.0f,0.0f));
					}
					
					pScrollBar->OnNotify(pWnd,PNM_SETSCROLLINFO,wParam,lParam);
				}
			}
			return;
		case PNM_SCROLLWINDOW:
			if (m_pListContent)
			{
				m_pListContent->SetScrollPos(CPDF_Point(0.0f, *(FX_FLOAT*)lParam));
				m_pListContent->ResetFace();
				m_pListContent->InvalidateRect(NULL);
			}
			return;
		case PNM_SETSCROLLPOS:
			if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar())
				pScrollBar->OnNotify(pWnd,PNM_SETSCROLLPOS,wParam,lParam);
			return;
		}
	}
}

void CPWL_IconList::SetSelect(FX_INT32 nIndex)
{
	m_pListContent->SetSelect(nIndex);
}

void CPWL_IconList::SetTopItem(FX_INT32 nIndex)
{
	m_pListContent->ScrollToItem(nIndex);
}

FX_INT32 CPWL_IconList::GetSelect() const
{
	return m_pListContent->GetSelect();
}

void CPWL_IconList::SetNotify(IPWL_IconList_Notify* pNotify)
{
	m_pListContent->SetNotify(pNotify);
}

void CPWL_IconList::EnableNotify(FX_BOOL bNotify)
{
	m_pListContent->EnableNotify(bNotify);
}

void CPWL_IconList::SetListData(FX_INT32 nItemIndex, void* pData)
{
	m_pListContent->SetListData(nItemIndex, pData);
}

void CPWL_IconList::SetListIcon(FX_INT32 nItemIndex, FX_INT32 nIconIndex)
{
	m_pListContent->SetListIcon(nItemIndex, nIconIndex);
}

void CPWL_IconList::SetListString(FX_INT32 nItemIndex, const CFX_WideString& str)
{
	m_pListContent->SetListString(nItemIndex, str);
}

CFX_WideString CPWL_IconList::GetListString(FX_INT32 nItemIndex) const
{
	return m_pListContent->GetListString(nItemIndex);
}

void CPWL_IconList::SetIconFillColor(const CPWL_Color& color)
{
	m_pListContent->SetIconFillColor(color);
}

FX_BOOL	CPWL_IconList::OnMouseWheel(short zDelta, const CPDF_Point & point)
{
	CPDF_Point ptScroll = m_pListContent->GetScrollPos();
	CPDF_Rect rcScroll = m_pListContent->GetScrollArea();
	CPDF_Rect rcContents = m_pListContent->GetClientRect();

	if (rcScroll.top - rcScroll.bottom > rcContents.Height())
	{
		CPDF_Point ptNew = ptScroll;

		if (zDelta > 0)
			ptNew.y += 30;
		else
			ptNew.y -= 30;

		if (ptNew.y > rcScroll.top)
			ptNew.y = rcScroll.top;
		if (ptNew.y < rcScroll.bottom + rcContents.Height())
			ptNew.y = rcScroll.bottom + rcContents.Height();
		if (ptNew.y < rcScroll.bottom)
			ptNew.y = rcScroll.bottom;

		if (ptNew.y != ptScroll.y)
		{
			m_pListContent->SetScrollPos(ptNew);
			m_pListContent->ResetFace();
			m_pListContent->InvalidateRect(NULL);
			
			if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar())
				pScrollBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptNew.y);

			return TRUE;
		}
	}

	return FALSE;
}

