// 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/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"

CPWL_ListBox::CPWL_ListBox(
    const CreateParams& cp,
    std::unique_ptr<IPWL_SystemHandler::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_SystemHandler* pSysHandler = GetSystemHandler();
    if (m_pListCtrl->IsItemSelected(i)) {
      if (pSysHandler->IsSelectionImplemented()) {
        CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device,
                                m_pListCtrl->GetItemEdit(i),
                                GetTextColor().ToFXColor(255), rcList, ptOffset,
                                nullptr, pSysHandler, m_pFormFiller.Get());
        pSysHandler->OutputSelectedRect(m_pFormFiller.Get(), rcItem);
      } else {
        pDevice->DrawFillRect(&mtUser2Device, rcItem,
                              ArgbEncode(255, 0, 51, 113));
        CPWL_EditImpl::DrawEdit(
            pDevice, mtUser2Device, m_pListCtrl->GetItemEdit(i),
            ArgbEncode(255, 255, 255, 255), rcList, ptOffset, nullptr,
            pSysHandler, m_pFormFiller.Get());
      }
    } else {
      CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device,
                              m_pListCtrl->GetItemEdit(i),
                              GetTextColor().ToFXColor(255), rcList, ptOffset,
                              nullptr, pSysHandler, nullptr);
    }
  }
}

bool CPWL_ListBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
  CPWL_Wnd::OnKeyDown(nChar, nFlag);

  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_pListCtrl->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
      break;
    case FWL_VKEY_Down:
      m_pListCtrl->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
      break;
    case FWL_VKEY_Home:
      m_pListCtrl->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
      break;
    case FWL_VKEY_Left:
      m_pListCtrl->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
      break;
    case FWL_VKEY_End:
      m_pListCtrl->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
      break;
    case FWL_VKEY_Right:
      m_pListCtrl->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
      break;
    case FWL_VKEY_Delete:
      break;
  }
  OnNotifySelectionChanged(true, nFlag);
  return true;
}

bool CPWL_ListBox::OnChar(uint16_t nChar, uint32_t nFlag) {
  CPWL_Wnd::OnChar(nChar, nFlag);

  if (!m_pListCtrl->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)))
    return false;

  OnNotifySelectionChanged(true, nFlag);
  return true;
}

bool CPWL_ListBox::OnLButtonDown(uint32_t nFlag, const CFX_PointF& point) {
  CPWL_Wnd::OnLButtonDown(nFlag, point);

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

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

  return true;
}

bool CPWL_ListBox::OnLButtonUp(uint32_t 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(uint32_t 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, IsSHIFTpressed(nFlag),
                             IsCTRLpressed(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, uint32_t nFlag) {
  if (!m_pFillerNotify)
    return false;

  ObservedPtr<CPWL_Wnd> thisObserved(this);

  WideString swChange = GetText();
  WideString strChangeEx;
  int nSelStart = 0;
  int nSelEnd = swChange.GetLength();
  bool bRC;
  bool bExit;
  std::tie(bRC, bExit) = m_pFillerNotify->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);
}

void CPWL_ListBox::ResetContent() {
  m_pListCtrl->Clear();
}

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

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

int32_t CPWL_ListBox::FindNext(int32_t nIndex, wchar_t nChar) const {
  return m_pListCtrl->FindNext(nIndex, nChar);
}

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(uint32_t nFlag,
                                const CFX_PointF& point,
                                const CFX_Vector& delta) {
  if (delta.y < 0)
    m_pListCtrl->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
  else
    m_pListCtrl->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));

  OnNotifySelectionChanged(false, nFlag);
  return true;
}
