// 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_ListBox.h"
#include "../../include/pdfwindow/PWL_Utils.h"
#include "../../include/pdfwindow/PWL_ScrollBar.h"
#include "../../include/pdfwindow/PWL_EditCtrl.h"
#include "../../include/pdfwindow/PWL_Edit.h"

#define IsFloatZero(f) ((f) < 0.0001 && (f) > -0.0001)
#define IsFloatBigger(fa, fb) ((fa) > (fb) && !IsFloatZero((fa) - (fb)))
#define IsFloatSmaller(fa, fb) ((fa) < (fb) && !IsFloatZero((fa) - (fb)))
#define IsFloatEqual(fa, fb) IsFloatZero((fa) - (fb))

/* ------------------------ CPWL_List_Notify ----------------------- */

CPWL_List_Notify::CPWL_List_Notify(CPWL_ListBox* pList) : m_pList(pList) {
  ASSERT(m_pList != NULL);
}

CPWL_List_Notify::~CPWL_List_Notify() {}

void CPWL_List_Notify::IOnSetScrollInfoY(FX_FLOAT fPlateMin,
                                         FX_FLOAT fPlateMax,
                                         FX_FLOAT fContentMin,
                                         FX_FLOAT fContentMax,
                                         FX_FLOAT fSmallStep,
                                         FX_FLOAT fBigStep) {
  PWL_SCROLL_INFO Info;

  Info.fPlateWidth = fPlateMax - fPlateMin;
  Info.fContentMin = fContentMin;
  Info.fContentMax = fContentMax;
  Info.fSmallStep = fSmallStep;
  Info.fBigStep = fBigStep;

  m_pList->OnNotify(m_pList, PNM_SETSCROLLINFO, SBT_VSCROLL, (intptr_t)&Info);

  if (CPWL_ScrollBar* pScroll = m_pList->GetVScrollBar()) {
    if (IsFloatBigger(Info.fPlateWidth, Info.fContentMax - Info.fContentMin) ||
        IsFloatEqual(Info.fPlateWidth, Info.fContentMax - Info.fContentMin)) {
      if (pScroll->IsVisible()) {
        pScroll->SetVisible(FALSE);
        m_pList->RePosChildWnd();
      }
    } else {
      if (!pScroll->IsVisible()) {
        pScroll->SetVisible(TRUE);
        m_pList->RePosChildWnd();
      }
    }
  }
}

void CPWL_List_Notify::IOnSetScrollPosY(FX_FLOAT fy) {
  m_pList->OnNotify(m_pList, PNM_SETSCROLLPOS, SBT_VSCROLL, (intptr_t)&fy);
}

void CPWL_List_Notify::IOnInvalidateRect(CPDF_Rect* pRect) {
  m_pList->InvalidateRect(pRect);
}

/* --------------------------- CPWL_ListBox ---------------------------- */

CPWL_ListBox::CPWL_ListBox()
    : m_pList(NULL),
      m_pListNotify(NULL),
      m_bMouseDown(FALSE),
      m_bHoverSel(FALSE),
      m_pFillerNotify(NULL) {
  m_pList = IFX_List::NewList();

  ASSERT(m_pList != NULL);
}

CPWL_ListBox::~CPWL_ListBox() {
  IFX_List::DelList(m_pList);
  delete m_pListNotify;
  m_pListNotify = NULL;
}

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

void CPWL_ListBox::OnCreated() {
  if (m_pList) {
    delete m_pListNotify;

    m_pList->SetFontMap(GetFontMap());
    m_pList->SetNotify(m_pListNotify = new CPWL_List_Notify(this));

    SetHoverSel(HasFlag(PLBS_HOVERSEL));
    m_pList->SetMultipleSel(HasFlag(PLBS_MULTIPLESEL));
    m_pList->SetFontSize(GetCreationParam().fFontSize);

    m_bHoverSel = HasFlag(PLBS_HOVERSEL);
  }
}

void CPWL_ListBox::OnDestroy() {
  delete m_pListNotify;
  m_pListNotify = NULL;
}

void CPWL_ListBox::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
  CPWL_Wnd::GetThisAppearanceStream(sAppStream);

  CFX_ByteTextBuf sListItems;

  if (m_pList) {
    CPDF_Rect rcPlate = m_pList->GetPlateRect();
    for (int32_t i = 0, sz = m_pList->GetCount(); i < sz; i++) {
      CPDF_Rect rcItem = m_pList->GetItemRect(i);

      if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom)
        continue;

      CPDF_Point ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f);
      if (m_pList->IsItemSelected(i)) {
        sListItems << CPWL_Utils::GetRectFillAppStream(
            rcItem, PWL_DEFAULT_SELBACKCOLOR);
        CFX_ByteString sItem =
            CPWL_Utils::GetEditAppStream(m_pList->GetItemEdit(i), ptOffset);
        if (sItem.GetLength() > 0) {
          sListItems << "BT\n"
                     << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELTEXTCOLOR)
                     << sItem << "ET\n";
        }
      } else {
        CFX_ByteString sItem =
            CPWL_Utils::GetEditAppStream(m_pList->GetItemEdit(i), ptOffset);
        if (sItem.GetLength() > 0) {
          sListItems << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor())
                     << sItem << "ET\n";
        }
      }
    }
  }

  if (sListItems.GetLength() > 0) {
    CFX_ByteTextBuf sClip;
    CPDF_Rect rcClient = GetClientRect();

    sClip << "q\n";
    sClip << rcClient.left << " " << rcClient.bottom << " "
          << rcClient.right - rcClient.left << " "
          << rcClient.top - rcClient.bottom << " re W n\n";

    sClip << sListItems << "Q\n";

    sAppStream << "/Tx BMC\n" << sClip << "EMC\n";
  }
}

void CPWL_ListBox::DrawThisAppearance(CFX_RenderDevice* pDevice,
                                      CPDF_Matrix* pUser2Device) {
  CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);

  if (m_pList) {
    CPDF_Rect rcPlate = m_pList->GetPlateRect();
    CPDF_Rect rcList = GetListRect();
    CPDF_Rect rcClient = GetClientRect();

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

      CPDF_Point ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f);
      if (IFX_Edit* pEdit = m_pList->GetItemEdit(i)) {
        CPDF_Rect rcContent = pEdit->GetContentRect();
        if (rcContent.Width() > rcClient.Width())
          rcItem.Intersect(rcList);
        else
          rcItem.Intersect(rcClient);
      }

      if (m_pList->IsItemSelected(i)) {
        //	CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcItem,
        // ArgbEncode(255,0,51,113));
        IFX_SystemHandler* pSysHandler = GetSystemHandler();
        if (pSysHandler && pSysHandler->IsSelectionImplemented()) {
          IFX_Edit::DrawEdit(
              pDevice, pUser2Device, m_pList->GetItemEdit(i),
              CPWL_Utils::PWLColorToFXColor(GetTextColor()),
              CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor()), rcList,
              ptOffset, NULL, pSysHandler, m_pFormFiller);
          pSysHandler->OutputSelectedRect(m_pFormFiller, rcItem);
        } else {
          CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcItem,
                                   ArgbEncode(255, 0, 51, 113));
          IFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i),
                             ArgbEncode(255, 255, 255, 255), 0, rcList,
                             ptOffset, NULL, pSysHandler, m_pFormFiller);
        }
      } else {
        IFX_SystemHandler* pSysHandler = GetSystemHandler();
        IFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i),
                           CPWL_Utils::PWLColorToFXColor(GetTextColor()),
                           CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor()),
                           rcList, ptOffset, NULL, pSysHandler, NULL);
      }
    }
  }
}

FX_BOOL CPWL_ListBox::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag) {
  CPWL_Wnd::OnKeyDown(nChar, nFlag);

  if (!m_pList)
    return FALSE;

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

  FX_BOOL bExit = FALSE;
  OnNotifySelChanged(TRUE, bExit, nFlag);

  return TRUE;
}

FX_BOOL CPWL_ListBox::OnChar(FX_WORD nChar, FX_DWORD nFlag) {
  CPWL_Wnd::OnChar(nChar, nFlag);

  if (!m_pList)
    return FALSE;

  if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)))
    return FALSE;

  FX_BOOL bExit = FALSE;
  OnNotifySelChanged(TRUE, bExit, nFlag);

  return TRUE;
}

FX_BOOL CPWL_ListBox::OnLButtonDown(const CPDF_Point& point, FX_DWORD nFlag) {
  CPWL_Wnd::OnLButtonDown(point, nFlag);

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

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

  return TRUE;
}

FX_BOOL CPWL_ListBox::OnLButtonUp(const CPDF_Point& point, FX_DWORD nFlag) {
  CPWL_Wnd::OnLButtonUp(point, nFlag);

  if (m_bMouseDown) {
    ReleaseCapture();
    m_bMouseDown = FALSE;
  }

  FX_BOOL bExit = FALSE;
  OnNotifySelChanged(FALSE, bExit, nFlag);

  return TRUE;
}

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

FX_BOOL CPWL_ListBox::OnMouseMove(const CPDF_Point& point, FX_DWORD nFlag) {
  CPWL_Wnd::OnMouseMove(point, nFlag);

  if (m_bHoverSel && !IsCaptureMouse() && ClientHitTest(point)) {
    if (m_pList)
      m_pList->Select(m_pList->GetItemIndex(point));
  }

  if (m_bMouseDown) {
    if (m_pList)
      m_pList->OnMouseMove(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
  }

  return TRUE;
}

void CPWL_ListBox::OnNotify(CPWL_Wnd* pWnd,
                            FX_DWORD msg,
                            intptr_t wParam,
                            intptr_t lParam) {
  CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);

  FX_FLOAT fPos;

  switch (msg) {
    case PNM_SETSCROLLINFO:
      switch (wParam) {
        case SBT_VSCROLL:
          if (CPWL_Wnd* pChild = GetVScrollBar()) {
            pChild->OnNotify(pWnd, PNM_SETSCROLLINFO, wParam, lParam);
          }
          break;
      }
      break;
    case PNM_SETSCROLLPOS:
      switch (wParam) {
        case SBT_VSCROLL:
          if (CPWL_Wnd* pChild = GetVScrollBar()) {
            pChild->OnNotify(pWnd, PNM_SETSCROLLPOS, wParam, lParam);
          }
          break;
      }
      break;
    case PNM_SCROLLWINDOW:
      fPos = *(FX_FLOAT*)lParam;
      switch (wParam) {
        case SBT_VSCROLL:
          if (m_pList)
            m_pList->SetScrollPos(CPDF_Point(0, fPos));
          break;
      }
      break;
  }
}

void CPWL_ListBox::KillFocus() {
  CPWL_Wnd::KillFocus();
}

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

  if (m_pList)
    m_pList->SetPlateRect(GetListRect());
}

void CPWL_ListBox::OnNotifySelChanged(FX_BOOL bKeyDown,
                                      FX_BOOL& bExit,
                                      FX_DWORD nFlag) {
  if (m_pFillerNotify) {
    FX_BOOL bRC = TRUE;
    CFX_WideString swChange = GetText();
    CFX_WideString strChangeEx;
    int nSelStart = 0;
    int nSelEnd = swChange.GetLength();
    m_pFillerNotify->OnBeforeKeyStroke(FALSE, GetAttachedData(), 0, swChange,
                                       strChangeEx, nSelStart, nSelEnd,
                                       bKeyDown, bRC, bExit, nFlag);
    if (bExit)
      return;

    m_pFillerNotify->OnAfterKeyStroke(FALSE, GetAttachedData(), bExit, nFlag);
  }
}

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

  return CPWL_Wnd::GetFocusRect();
}

void CPWL_ListBox::AddString(const FX_WCHAR* string) {
  if (m_pList) {
    m_pList->AddString(string);
  }
}

CFX_WideString CPWL_ListBox::GetText() const {
  if (m_pList)
    return m_pList->GetText();

  return L"";
}

void CPWL_ListBox::SetFontSize(FX_FLOAT fFontSize) {
  if (m_pList)
    m_pList->SetFontSize(fFontSize);
}

FX_FLOAT CPWL_ListBox::GetFontSize() const {
  if (m_pList)
    return m_pList->GetFontSize();
  return 0.0f;
}

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

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

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

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

void CPWL_ListBox::ResetContent() {
  if (m_pList)
    m_pList->Empty();
}

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

FX_BOOL CPWL_ListBox::IsMultipleSel() const {
  if (m_pList)
    return m_pList->IsMultipleSel();

  return FALSE;
}

int32_t CPWL_ListBox::GetCaretIndex() const {
  if (m_pList)
    return m_pList->GetCaret();

  return -1;
}

int32_t CPWL_ListBox::GetCurSel() const {
  if (m_pList)
    return m_pList->GetSelect();

  return -1;
}

FX_BOOL CPWL_ListBox::IsItemSelected(int32_t nItemIndex) const {
  if (m_pList)
    return m_pList->IsItemSelected(nItemIndex);

  return FALSE;
}

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

  return -1;
}

int32_t CPWL_ListBox::GetCount() const {
  if (m_pList)
    return m_pList->GetCount();

  return 0;
}

int32_t CPWL_ListBox::FindNext(int32_t nIndex, FX_WCHAR nChar) const {
  if (m_pList)
    return m_pList->FindNext(nIndex, nChar);

  return nIndex;
}

CPDF_Rect CPWL_ListBox::GetContentRect() const {
  if (m_pList)
    return m_pList->GetContentRect();

  return CPDF_Rect();
}

FX_FLOAT CPWL_ListBox::GetFirstHeight() const {
  if (m_pList)
    return m_pList->GetFirstHeight();

  return 0.0f;
}

CPDF_Rect CPWL_ListBox::GetListRect() const {
  return CPWL_Utils::DeflateRect(
      GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
}

FX_BOOL CPWL_ListBox::OnMouseWheel(short zDelta,
                                   const CPDF_Point& point,
                                   FX_DWORD nFlag) {
  if (!m_pList)
    return FALSE;

  if (zDelta < 0) {
    m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
  } else {
    m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
  }

  FX_BOOL bExit = FALSE;
  OnNotifySelChanged(FALSE, bExit, nFlag);
  return TRUE;
}
