// Copyright 2014 The PDFium Authors
// 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/pwl/cpwl_list_box.h"

#include <sstream>
#include <utility>

#include "core/fxge/cfx_renderdevice.h"
#include "fpdfsdk/pwl/cpwl_edit.h"
#include "fpdfsdk/pwl/cpwl_edit_impl.h"
#include "fpdfsdk/pwl/cpwl_scroll_bar.h"
#include "fpdfsdk/pwl/ipwl_fillernotify.h"
#include "public/fpdf_fwlevent.h"
#include "third_party/base/numerics/safe_conversions.h"

CPWL_ListBox::CPWL_ListBox(
    const CreateParams& cp,
    std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData)
    : CPWL_Wnd(cp, std::move(pAttachedData)),
      m_pListCtrl(std::make_unique<CPWL_ListCtrl>()) {}

CPWL_ListBox::~CPWL_ListBox() = default;

void CPWL_ListBox::OnCreated() {
  m_pListCtrl->SetFontMap(GetFontMap());
  m_pListCtrl->SetNotify(this);

  SetHoverSel(HasFlag(PLBS_HOVERSEL));
  m_pListCtrl->SetMultipleSel(HasFlag(PLBS_MULTIPLESEL));
  m_pListCtrl->SetFontSize(GetCreationParams()->fFontSize);

  m_bHoverSel = HasFlag(PLBS_HOVERSEL);
}

void CPWL_ListBox::OnDestroy() {
  // Make sure the notifier is removed from the list as we are about to
  // destroy the notifier and don't want to leave a dangling pointer.
  m_pListCtrl->SetNotify(nullptr);
}

void CPWL_ListBox::DrawThisAppearance(CFX_RenderDevice* pDevice,
                                      const CFX_Matrix& mtUser2Device) {
  CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device);

  CFX_FloatRect rcPlate = m_pListCtrl->GetPlateRect();
  CFX_FloatRect rcList = GetListRect();
  CFX_FloatRect rcClient = GetClientRect();

  for (int32_t i = 0, sz = m_pListCtrl->GetCount(); i < sz; i++) {
    CFX_FloatRect rcItem = m_pListCtrl->GetItemRect(i);
    if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom)
      continue;

    CFX_PointF ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f);
    if (CPWL_EditImpl* pEdit = m_pListCtrl->GetItemEdit(i)) {
      CFX_FloatRect rcContent = pEdit->GetContentRect();
      rcItem.Intersect(rcContent.Width() > rcClient.Width() ? rcList
                                                            : rcClient);
    }

    IPWL_FillerNotify* pSysHandler = GetFillerNotify();
    if (m_pListCtrl->IsItemSelected(i)) {
      if (pSysHandler->IsSelectionImplemented()) {
        m_pListCtrl->GetItemEdit(i)->DrawEdit(
            pDevice, mtUser2Device, GetTextColor().ToFXColor(255), rcList,
            ptOffset, nullptr, pSysHandler, GetAttachedData());
        pSysHandler->OutputSelectedRect(GetAttachedData(), rcItem);
      } else {
        pDevice->DrawFillRect(&mtUser2Device, rcItem,
                              ArgbEncode(255, 0, 51, 113));
        m_pListCtrl->GetItemEdit(i)->DrawEdit(
            pDevice, mtUser2Device, ArgbEncode(255, 255, 255, 255), rcList,
            ptOffset, nullptr, pSysHandler, GetAttachedData());
      }
    } else {
      m_pListCtrl->GetItemEdit(i)->DrawEdit(
          pDevice, mtUser2Device, GetTextColor().ToFXColor(255), rcList,
          ptOffset, nullptr, pSysHandler, nullptr);
    }
  }
}

bool CPWL_ListBox::OnKeyDown(FWL_VKEYCODE nKeyCode, Mask<FWL_EVENTFLAG> nFlag) {
  CPWL_Wnd::OnKeyDown(nKeyCode, nFlag);

  switch (nKeyCode) {
    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 (nKeyCode) {
    case FWL_VKEY_Up:
      m_pListCtrl->OnVK_UP(IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag));
      break;
    case FWL_VKEY_Down:
      m_pListCtrl->OnVK_DOWN(IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag));
      break;
    case FWL_VKEY_Home:
      m_pListCtrl->OnVK_HOME(IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag));
      break;
    case FWL_VKEY_Left:
      m_pListCtrl->OnVK_LEFT(IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag));
      break;
    case FWL_VKEY_End:
      m_pListCtrl->OnVK_END(IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag));
      break;
    case FWL_VKEY_Right:
      m_pListCtrl->OnVK_RIGHT(IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag));
      break;
    default:
      break;
  }
  OnNotifySelectionChanged(true, nFlag);
  return true;
}

bool CPWL_ListBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
  CPWL_Wnd::OnChar(nChar, nFlag);

  if (!m_pListCtrl->OnChar(nChar, IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag)))
    return false;

  OnNotifySelectionChanged(true, nFlag);
  return true;
}

bool CPWL_ListBox::OnLButtonDown(Mask<FWL_EVENTFLAG> nFlag,
                                 const CFX_PointF& point) {
  CPWL_Wnd::OnLButtonDown(nFlag, point);

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

    m_pListCtrl->OnMouseDown(point, IsSHIFTKeyDown(nFlag),
                             IsCTRLKeyDown(nFlag));
  }

  return true;
}

bool CPWL_ListBox::OnLButtonUp(Mask<FWL_EVENTFLAG> nFlag,
                               const CFX_PointF& point) {
  CPWL_Wnd::OnLButtonUp(nFlag, point);

  if (m_bMouseDown) {
    ReleaseCapture();
    m_bMouseDown = false;
  }
  OnNotifySelectionChanged(false, nFlag);
  return true;
}

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

bool CPWL_ListBox::OnMouseMove(Mask<FWL_EVENTFLAG> nFlag,
                               const CFX_PointF& point) {
  CPWL_Wnd::OnMouseMove(nFlag, point);

  if (m_bHoverSel && !IsCaptureMouse() && ClientHitTest(point))
    m_pListCtrl->Select(m_pListCtrl->GetItemIndex(point));
  if (m_bMouseDown)
    m_pListCtrl->OnMouseMove(point, IsSHIFTKeyDown(nFlag),
                             IsCTRLKeyDown(nFlag));

  return true;
}

void CPWL_ListBox::SetScrollInfo(const PWL_SCROLL_INFO& info) {
  if (CPWL_Wnd* pChild = GetVScrollBar())
    pChild->SetScrollInfo(info);
}

void CPWL_ListBox::SetScrollPosition(float pos) {
  if (CPWL_Wnd* pChild = GetVScrollBar())
    pChild->SetScrollPosition(pos);
}

void CPWL_ListBox::ScrollWindowVertically(float pos) {
  m_pListCtrl->SetScrollPos(CFX_PointF(0, pos));
}

bool CPWL_ListBox::RePosChildWnd() {
  if (!CPWL_Wnd::RePosChildWnd())
    return false;

  m_pListCtrl->SetPlateRect(GetListRect());
  return true;
}

bool CPWL_ListBox::OnNotifySelectionChanged(bool bKeyDown,
                                            Mask<FWL_EVENTFLAG> nFlag) {
  ObservedPtr<CPWL_Wnd> thisObserved(this);

  WideString swChange = GetText();
  WideString strChangeEx;
  int nSelStart = 0;
  int nSelEnd = pdfium::base::checked_cast<int>(swChange.GetLength());
  bool bRC;
  bool bExit;
  std::tie(bRC, bExit) = GetFillerNotify()->OnBeforeKeyStroke(
      GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, bKeyDown,
      nFlag);

  if (!thisObserved)
    return false;

  return bExit;
}

CFX_FloatRect CPWL_ListBox::GetFocusRect() const {
  if (m_pListCtrl->IsMultipleSel()) {
    CFX_FloatRect rcCaret = m_pListCtrl->GetItemRect(m_pListCtrl->GetCaret());
    rcCaret.Intersect(GetClientRect());
    return rcCaret;
  }

  return CPWL_Wnd::GetFocusRect();
}

void CPWL_ListBox::AddString(const WideString& str) {
  m_pListCtrl->AddString(str);
}

WideString CPWL_ListBox::GetText() {
  return m_pListCtrl->GetText();
}

void CPWL_ListBox::SetFontSize(float fFontSize) {
  m_pListCtrl->SetFontSize(fFontSize);
}

float CPWL_ListBox::GetFontSize() const {
  return m_pListCtrl->GetFontSize();
}

void CPWL_ListBox::OnSetScrollInfoY(float fPlateMin,
                                    float fPlateMax,
                                    float fContentMin,
                                    float fContentMax,
                                    float fSmallStep,
                                    float fBigStep) {
  PWL_SCROLL_INFO Info;
  Info.fPlateWidth = fPlateMax - fPlateMin;
  Info.fContentMin = fContentMin;
  Info.fContentMax = fContentMax;
  Info.fSmallStep = fSmallStep;
  Info.fBigStep = fBigStep;
  SetScrollInfo(Info);

  CPWL_ScrollBar* pScroll = GetVScrollBar();
  if (!pScroll)
    return;

  if (FXSYS_IsFloatBigger(Info.fPlateWidth,
                          Info.fContentMax - Info.fContentMin) ||
      FXSYS_IsFloatEqual(Info.fPlateWidth,
                         Info.fContentMax - Info.fContentMin)) {
    if (pScroll->IsVisible()) {
      pScroll->SetVisible(false);
      RePosChildWnd();
    }
  } else {
    if (!pScroll->IsVisible()) {
      pScroll->SetVisible(true);
      RePosChildWnd();
    }
  }
}

void CPWL_ListBox::OnSetScrollPosY(float fy) {
  SetScrollPosition(fy);
}

void CPWL_ListBox::OnInvalidateRect(const CFX_FloatRect& rect) {
  InvalidateRect(&rect);
}

void CPWL_ListBox::Select(int32_t nItemIndex) {
  m_pListCtrl->Select(nItemIndex);
}

void CPWL_ListBox::Deselect(int32_t nItemIndex) {
  m_pListCtrl->Deselect(nItemIndex);
}

void CPWL_ListBox::SetCaret(int32_t nItemIndex) {
  m_pListCtrl->SetCaret(nItemIndex);
}

void CPWL_ListBox::SetTopVisibleIndex(int32_t nItemIndex) {
  m_pListCtrl->SetTopItem(nItemIndex);
}

void CPWL_ListBox::ScrollToListItem(int32_t nItemIndex) {
  m_pListCtrl->ScrollToListItem(nItemIndex);
}

bool CPWL_ListBox::IsMultipleSel() const {
  return m_pListCtrl->IsMultipleSel();
}

int32_t CPWL_ListBox::GetCaretIndex() const {
  return m_pListCtrl->GetCaret();
}

int32_t CPWL_ListBox::GetCurSel() const {
  return m_pListCtrl->GetSelect();
}

bool CPWL_ListBox::IsItemSelected(int32_t nItemIndex) const {
  return m_pListCtrl->IsItemSelected(nItemIndex);
}

int32_t CPWL_ListBox::GetTopVisibleIndex() const {
  m_pListCtrl->ScrollToListItem(m_pListCtrl->GetFirstSelected());
  return m_pListCtrl->GetTopItem();
}

int32_t CPWL_ListBox::GetCount() const {
  return m_pListCtrl->GetCount();
}

CFX_FloatRect CPWL_ListBox::GetContentRect() const {
  return m_pListCtrl->GetContentRect();
}

float CPWL_ListBox::GetFirstHeight() const {
  return m_pListCtrl->GetFirstHeight();
}

CFX_FloatRect CPWL_ListBox::GetListRect() const {
  float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth());
  return GetWindowRect().GetDeflated(width, width);
}

bool CPWL_ListBox::OnMouseWheel(Mask<FWL_EVENTFLAG> nFlag,
                                const CFX_PointF& point,
                                const CFX_Vector& delta) {
  if (delta.y < 0)
    m_pListCtrl->OnVK_DOWN(IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag));
  else
    m_pListCtrl->OnVK_UP(IsSHIFTKeyDown(nFlag), IsCTRLKeyDown(nFlag));

  OnNotifySelectionChanged(false, nFlag);
  return true;
}
