// 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 "fpdfsdk/pdfwindow/PWL_IconList.h"

#include "fpdfsdk/pdfwindow/PWL_Label.h"
#include "fpdfsdk/pdfwindow/PWL_ListCtrl.h"
#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
#include "fpdfsdk/pdfwindow/PWL_Utils.h"
#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
#include "public/fpdf_fwlevent.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()
    : 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,
                                            CFX_Matrix* pUser2Device) {
  CFX_FloatRect 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()));
    }
  }

  CFX_FloatRect 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(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(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() {
  CFX_FloatRect 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(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()) {
    CFX_FloatRect 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);
  }
}

FX_BOOL CPWL_IconList_Content::OnLButtonDown(const CFX_FloatPoint& point,
                                             uint32_t nFlag) {
  SetFocus();

  SetCapture();
  m_bMouseDown = TRUE;

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

  return TRUE;
}

FX_BOOL CPWL_IconList_Content::OnLButtonUp(const CFX_FloatPoint& point,
                                           uint32_t nFlag) {
  m_bMouseDown = FALSE;
  ReleaseCapture();

  return TRUE;
}

FX_BOOL CPWL_IconList_Content::OnMouseMove(const CFX_FloatPoint& point,
                                           uint32_t nFlag) {
  if (m_bMouseDown) {
    int32_t nItemIndex = FindItemIndex(point);
    SetSelect(nItemIndex);
    ScrollToItem(nItemIndex);
  }

  return TRUE;
}

FX_BOOL CPWL_IconList_Content::OnKeyDown(uint16_t nChar, uint32_t 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 CFX_FloatPoint& 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)) {
      CFX_FloatRect rcWnd = pChild->ChildToParent(pChild->GetWindowRect());

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

  return nIndex;
}

void CPWL_IconList_Content::ScrollToItem(int32_t nItemIndex) {
  CFX_FloatRect rcClient = GetClientRect();

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

    if (!(rcWnd.bottom > rcClient.bottom && rcWnd.top < rcClient.top)) {
      CFX_FloatPoint 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(FX_BOOL bNotify) {
  m_bEnableNotify = bNotify;
}

void CPWL_IconList_Content::SelectItem(int32_t nItemIndex, FX_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(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,
                             uint32_t 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(CFX_FloatPoint(0.0f, 0.0f));
            }

            pScrollBar->OnNotify(pWnd, PNM_SETSCROLLINFO, wParam, lParam);
          }
        }
        return;
      case PNM_SCROLLWINDOW:
        if (m_pListContent) {
          m_pListContent->SetScrollPos(
              CFX_FloatPoint(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(FX_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);
}

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

  if (rcScroll.top - rcScroll.bottom > rcContents.Height()) {
    CFX_FloatPoint 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;
}
