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

#ifndef XFA_FWL_CORE_IFWL_LISTBOX_H_
#define XFA_FWL_CORE_IFWL_LISTBOX_H_

#include <memory>

#include "xfa/fwl/core/cfwl_event.h"
#include "xfa/fwl/core/cfwl_listitem.h"
#include "xfa/fwl/core/cfwl_widgetproperties.h"
#include "xfa/fwl/core/ifwl_dataprovider.h"
#include "xfa/fwl/core/ifwl_edit.h"
#include "xfa/fwl/core/ifwl_listbox.h"
#include "xfa/fwl/core/ifwl_widget.h"

#define FWL_STYLEEXT_LTB_MultiSelection (1L << 0)
#define FWL_STYLEEXT_LTB_ShowScrollBarAlaways (1L << 2)
#define FWL_STYLEEXT_LTB_MultiColumn (1L << 3)
#define FWL_STYLEEXT_LTB_LeftAlign (0L << 4)
#define FWL_STYLEEXT_LTB_CenterAlign (1L << 4)
#define FWL_STYLEEXT_LTB_RightAlign (2L << 4)
#define FWL_STYLEEXT_LTB_MultiLine (1L << 6)
#define FWL_STYLEEXT_LTB_OwnerDraw (1L << 7)
#define FWL_STYLEEXT_LTB_Icon (1L << 8)
#define FWL_STYLEEXT_LTB_Check (1L << 9)
#define FWL_STYLEEXT_LTB_AlignMask (3L << 4)
#define FWL_STYLEEXT_LTB_ShowScrollBarFocus (1L << 10)
#define FWL_ITEMSTATE_LTB_Selected (1L << 0)
#define FWL_ITEMSTATE_LTB_Focused (1L << 1)
#define FWL_ITEMSTATE_LTB_Checked (1L << 2)

class CFWL_MsgKillFocus;
class CFWL_MsgMouse;
class CFWL_MsgMouseWheel;
class CFX_DIBitmap;

FWL_EVENT_DEF(CFWL_EvtLtbSelChanged,
              CFWL_EventType::SelectChanged,
              CFX_Int32Array iarraySels;)

FWL_EVENT_DEF(CFWL_EvtLtbDrawItem,
              CFWL_EventType::DrawItem,
              CFX_Graphics* m_pGraphics;
              CFX_Matrix m_matrix;
              int32_t m_index;
              CFX_RectF m_rect;)

class IFWL_ListBoxDP : public IFWL_DataProvider {
 public:
  virtual int32_t CountItems(const IFWL_Widget* pWidget) = 0;
  virtual CFWL_ListItem* GetItem(const IFWL_Widget* pWidget,
                                 int32_t nIndex) = 0;
  virtual int32_t GetItemIndex(IFWL_Widget* pWidget, CFWL_ListItem* pItem) = 0;
  virtual bool SetItemIndex(IFWL_Widget* pWidget,
                            CFWL_ListItem* pItem,
                            int32_t nIndex) = 0;
  virtual uint32_t GetItemStyles(IFWL_Widget* pWidget,
                                 CFWL_ListItem* pItem) = 0;
  virtual void GetItemText(IFWL_Widget* pWidget,
                           CFWL_ListItem* pItem,
                           CFX_WideString& wsText) = 0;
  virtual void GetItemRect(IFWL_Widget* pWidget,
                           CFWL_ListItem* pItem,
                           CFX_RectF& rtItem) = 0;
  virtual void* GetItemData(IFWL_Widget* pWidget, CFWL_ListItem* pItem) = 0;
  virtual void SetItemStyles(IFWL_Widget* pWidget,
                             CFWL_ListItem* pItem,
                             uint32_t dwStyle) = 0;
  virtual void SetItemText(IFWL_Widget* pWidget,
                           CFWL_ListItem* pItem,
                           const FX_WCHAR* pszText) = 0;
  virtual void SetItemRect(IFWL_Widget* pWidget,
                           CFWL_ListItem* pItem,
                           const CFX_RectF& rtItem) = 0;
  virtual FX_FLOAT GetItemHeight(IFWL_Widget* pWidget) = 0;
  virtual CFX_DIBitmap* GetItemIcon(IFWL_Widget* pWidget,
                                    CFWL_ListItem* pItem) = 0;
  virtual void GetItemCheckRect(IFWL_Widget* pWidget,
                                CFWL_ListItem* pItem,
                                CFX_RectF& rtCheck) = 0;
  virtual void SetItemCheckRect(IFWL_Widget* pWidget,
                                CFWL_ListItem* pItem,
                                const CFX_RectF& rtCheck) = 0;
  virtual uint32_t GetItemCheckState(IFWL_Widget* pWidget,
                                     CFWL_ListItem* pItem) = 0;
  virtual void SetItemCheckState(IFWL_Widget* pWidget,
                                 CFWL_ListItem* pItem,
                                 uint32_t dwCheckState) = 0;
};

class IFWL_ListBox : public IFWL_Widget {
 public:
  IFWL_ListBox(const IFWL_App* app,
               std::unique_ptr<CFWL_WidgetProperties> properties,
               IFWL_Widget* pOuter);
  ~IFWL_ListBox() override;

  // IFWL_Widget
  FWL_Type GetClassID() const override;
  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
  void Update() override;
  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
  void DrawWidget(CFX_Graphics* pGraphics,
                  const CFX_Matrix* pMatrix = nullptr) override;
  void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override;
  void OnProcessMessage(CFWL_Message* pMessage) override;
  void OnProcessEvent(CFWL_Event* pEvent) override;
  void OnDrawWidget(CFX_Graphics* pGraphics,
                    const CFX_Matrix* pMatrix) override;

  int32_t CountSelItems();
  CFWL_ListItem* GetSelItem(int32_t nIndexSel);
  int32_t GetSelIndex(int32_t nIndex);
  void SetSelItem(CFWL_ListItem* hItem, bool bSelect = true);
  void GetItemText(CFWL_ListItem* hItem, CFX_WideString& wsText);
  void GetScrollPos(FX_FLOAT& fPos, bool bVert = true);

 protected:
  CFWL_ListItem* GetItem(CFWL_ListItem* hItem, uint32_t dwKeyCode);
  void SetSelection(CFWL_ListItem* hStart, CFWL_ListItem* hEnd, bool bSelected);
  CFWL_ListItem* GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy);
  bool ScrollToVisible(CFWL_ListItem* hItem);
  FX_FLOAT CalcItemHeight();
  void InitScrollBar(bool bVert = true);
  bool IsShowScrollBar(bool bVert);
  FX_FLOAT GetItemHeight() const { return m_fItemHeight; }
  IFWL_ScrollBar* GetVertScrollBar() const { return m_pVertScrollBar.get(); }
  const CFX_RectF& GetRTClient() const { return m_rtClient; }

 private:
  void SetSelectionDirect(CFWL_ListItem* hItem, bool bSelect);
  bool IsItemSelected(CFWL_ListItem* hItem);
  void ClearSelection();
  void SelectAll();
  CFWL_ListItem* GetFocusedItem();
  void SetFocusItem(CFWL_ListItem* hItem);
  bool GetItemCheckRect(CFWL_ListItem* hItem, CFX_RectF& rtCheck);
  bool SetItemChecked(CFWL_ListItem* hItem, bool bChecked);
  bool GetItemChecked(CFWL_ListItem* hItem);
  void DrawBkground(CFX_Graphics* pGraphics,
                    IFWL_ThemeProvider* pTheme,
                    const CFX_Matrix* pMatrix = nullptr);
  void DrawItems(CFX_Graphics* pGraphics,
                 IFWL_ThemeProvider* pTheme,
                 const CFX_Matrix* pMatrix = nullptr);
  void DrawItem(CFX_Graphics* pGraphics,
                IFWL_ThemeProvider* pTheme,
                CFWL_ListItem* hItem,
                int32_t Index,
                const CFX_RectF& rtItem,
                const CFX_Matrix* pMatrix = nullptr);
  void DrawStatic(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme);
  CFX_SizeF CalcSize(bool bAutoSize = false);
  void GetItemSize(CFX_SizeF& size,
                   CFWL_ListItem* hItem,
                   FX_FLOAT fWidth,
                   FX_FLOAT fHeight,
                   bool bAutoSize = false);
  FX_FLOAT GetMaxTextWidth();
  FX_FLOAT GetScrollWidth();
  void ProcessSelChanged();
  void OnFocusChanged(CFWL_Message* pMsg, bool bSet = true);
  void OnLButtonDown(CFWL_MsgMouse* pMsg);
  void OnLButtonUp(CFWL_MsgMouse* pMsg);
  void OnMouseWheel(CFWL_MsgMouseWheel* pMsg);
  void OnKeyDown(CFWL_MsgKey* pMsg);
  void OnVK(CFWL_ListItem* hItem, bool bShift, bool bCtrl);
  bool OnScroll(IFWL_ScrollBar* pScrollBar, FWL_SCBCODE dwCode, FX_FLOAT fPos);
  void DispatchSelChangedEv();

  CFX_RectF m_rtClient;
  CFX_RectF m_rtStatic;
  CFX_RectF m_rtConent;
  std::unique_ptr<IFWL_ScrollBar> m_pHorzScrollBar;
  std::unique_ptr<IFWL_ScrollBar> m_pVertScrollBar;
  uint32_t m_dwTTOStyles;
  int32_t m_iTTOAligns;
  CFWL_ListItem* m_hAnchor;
  FX_FLOAT m_fItemHeight;
  FX_FLOAT m_fScorllBarWidth;
  bool m_bLButtonDown;
  IFWL_ThemeProvider* m_pScrollBarTP;
};

#endif  // XFA_FWL_CORE_IFWL_LISTBOX_H_
