// 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 (IsEnabled())
		{
			CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient,
				CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_SELBACKCOLOR, GetTransparency()));
		}
		else
		{
			CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient,
				CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_LIGHTGRAYCOLOR, 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(), GetTransparency());
}

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

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

}

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(int32_t nIconIndex)
{
	m_nIconIndex = nIconIndex;
}

void CPWL_IconList_Item::SetText(const CFX_WideString& str)
{
	m_pText->SetText(str.c_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);

	InvalidateRect();
}

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

	InvalidateRect();
}

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

CPWL_IconList_Content::CPWL_IconList_Content(int32_t 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 (int32_t 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);
	}

	SetItemSpace(PWL_IconList_ITEM_SPACE);
	ResetContent(0);

	if (CPWL_Wnd * pParent = GetParentWindow())
	{
		CPDF_Rect rcScroll = GetScrollArea();
		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, (intptr_t)&sInfo);
	}
}

bool	CPWL_IconList_Content::OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag)
{
	SetFocus();

	SetCapture();
	m_bMouseDown = true;

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

	return true;
}

bool	CPWL_IconList_Content::OnLButtonUp(const CPDF_Point & point, FX_DWORD nFlag)
{
	m_bMouseDown = false;
	ReleaseCapture();

	return true;
}

bool CPWL_IconList_Content::OnMouseMove(const CPDF_Point & point, FX_DWORD nFlag)
{
	if (m_bMouseDown)
	{
		int32_t nItemIndex = FindItemIndex(point);
		SetSelect(nItemIndex);
		ScrollToItem(nItemIndex);
	}

	return true;
}

bool	CPWL_IconList_Content::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag)
{
	switch (nChar)
	{
	case FWL_VKEY_Up:
		if (m_nSelectIndex > 0)
		{
			int32_t nItemIndex = m_nSelectIndex - 1;
			SetSelect(nItemIndex);
			ScrollToItem(nItemIndex);
		}
		return true;
	case FWL_VKEY_Down:
		if (m_nSelectIndex < m_nListCount-1)
		{
			int32_t nItemIndex = m_nSelectIndex + 1;
			SetSelect(nItemIndex);
			ScrollToItem(nItemIndex);
		}
		return true;
	}

	return false;
}

int32_t CPWL_IconList_Content::FindItemIndex(const CPDF_Point& point)
{
	int32_t nIndex = 0;
	for (int32_t 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(int32_t 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();
			}

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

void CPWL_IconList_Content::SetSelect(int32_t nIndex)
{
	if (m_nSelectIndex != nIndex)
	{
		SelectItem(m_nSelectIndex, false);
		SelectItem(nIndex, true);
		m_nSelectIndex = nIndex;

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

int32_t 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(bool bNotify)
{
	m_bEnableNotify = bNotify;
}

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

CPWL_IconList_Item* CPWL_IconList_Content::GetListItem(int32_t 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(int32_t nItemIndex, void* pData)
{
	if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
		pItem->SetData(pData);
}

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

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

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

	return L"";
}

void CPWL_IconList_Content::SetIconFillColor(const CPWL_Color& color)
{
	for (int32_t 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(int32_t 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 = GetVScrollBar())
	{
		pScrollBar->RemoveFlag(PWS_AUTOTRANSPARENT);
		pScrollBar->SetTransparency(255);
		pScrollBar->SetNotifyForever(true);
	}
}

void CPWL_IconList::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, intptr_t wParam, intptr_t 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 = 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 = GetVScrollBar())
				pScrollBar->OnNotify(pWnd,PNM_SETSCROLLPOS,wParam,lParam);
			return;
		}
	}
}

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

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

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

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

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

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

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

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

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

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

bool	CPWL_IconList::OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag)
{
	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 = GetVScrollBar())
				pScrollBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (intptr_t)&ptNew.y);

			return true;
		}
	}

	return false;
}

