// 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 FPDFSDK_PWL_CPWL_LIST_CTRL_H_
#define FPDFSDK_PWL_CPWL_LIST_CTRL_H_

#include <map>
#include <memory>
#include <vector>

#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/unowned_ptr.h"

class CPWL_EditImpl;
class CPWL_EditImpl_Iterator;
class IPVT_FontMap;

class CPWL_ListCtrl {
 public:
  class NotifyIface {
   public:
    virtual ~NotifyIface();

    virtual void OnSetScrollInfoY(float fPlateMin,
                                  float fPlateMax,
                                  float fContentMin,
                                  float fContentMax,
                                  float fSmallStep,
                                  float fBigStep) = 0;
    virtual void OnSetScrollPosY(float fy) = 0;
    virtual void OnInvalidateRect(const CFX_FloatRect& rect) = 0;
  };

  CPWL_ListCtrl();
  ~CPWL_ListCtrl();

  void SetNotify(NotifyIface* pNotify) { m_pNotify = pNotify; }
  void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl);
  void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl);
  void OnVK_UP(bool bShift, bool bCtrl);
  void OnVK_DOWN(bool bShift, bool bCtrl);
  void OnVK_LEFT(bool bShift, bool bCtrl);
  void OnVK_RIGHT(bool bShift, bool bCtrl);
  void OnVK_HOME(bool bShift, bool bCtrl);
  void OnVK_END(bool bShift, bool bCtrl);
  bool OnChar(uint16_t nChar, bool bShift, bool bCtrl);

  void SetScrollPos(const CFX_PointF& point);
  void ScrollToListItem(int32_t nItemIndex);
  CFX_FloatRect GetItemRect(int32_t nIndex) const;
  int32_t GetCaret() const { return m_nCaretIndex; }
  int32_t GetSelect() const { return m_nSelItem; }
  int32_t GetTopItem() const;
  CFX_FloatRect GetContentRect() const;

  int32_t GetItemIndex(const CFX_PointF& point) const;
  void AddString(const WideString& str);
  void SetTopItem(int32_t nIndex);
  void Select(int32_t nItemIndex);
  void Deselect(int32_t nItemIndex);
  void SetCaret(int32_t nItemIndex);
  void Clear();
  void Cancel();
  WideString GetText() const;

  void SetFontMap(IPVT_FontMap* pFontMap) { m_pFontMap = pFontMap; }
  void SetFontSize(float fFontSize) { m_fFontSize = fFontSize; }
  CFX_FloatRect GetPlateRect() const { return m_rcPlate; }
  void SetPlateRect(const CFX_FloatRect& rect);

  float GetFontSize() const { return m_fFontSize; }
  CPWL_EditImpl* GetItemEdit(int32_t nIndex) const;
  int32_t GetCount() const;
  bool IsItemSelected(int32_t nIndex) const;
  float GetFirstHeight() const;
  void SetMultipleSel(bool bMultiple) { m_bMultiple = bMultiple; }
  bool IsMultipleSel() const { return m_bMultiple; }
  int32_t FindNext(int32_t nIndex, wchar_t nChar) const;
  int32_t GetFirstSelected() const;

 private:
  class Item {
   public:
    Item();
    ~Item();

    void SetFontMap(IPVT_FontMap* pFontMap);
    CPWL_EditImpl* GetEdit() const { return m_pEdit.get(); }

    void SetRect(const CFX_FloatRect& rect) { m_rcListItem = rect; }
    void SetSelect(bool bSelected) { m_bSelected = bSelected; }
    void SetText(const WideString& text);
    void SetFontSize(float fFontSize);
    WideString GetText() const;

    CFX_FloatRect GetRect() const { return m_rcListItem; }
    bool IsSelected() const { return m_bSelected; }
    float GetItemHeight() const;
    uint16_t GetFirstChar() const;

   private:
    CPWL_EditImpl_Iterator* GetIterator() const;

    bool m_bSelected = false;
    CFX_FloatRect m_rcListItem;
    std::unique_ptr<CPWL_EditImpl> const m_pEdit;
  };

  class SelectState {
   public:
    enum State { DESELECTING = -1, NORMAL = 0, SELECTING = 1 };
    using const_iterator = std::map<int32_t, State>::const_iterator;

    SelectState();
    ~SelectState();

    void Add(int32_t nItemIndex);
    void Add(int32_t nBeginIndex, int32_t nEndIndex);
    void Sub(int32_t nItemIndex);
    void Sub(int32_t nBeginIndex, int32_t nEndIndex);
    void DeselectAll();
    void Done();

    const_iterator begin() const { return m_Items.begin(); }
    const_iterator end() const { return m_Items.end(); }

   private:
    std::map<int32_t, State> m_Items;
  };

  CFX_PointF InToOut(const CFX_PointF& point) const;
  CFX_PointF OutToIn(const CFX_PointF& point) const;
  CFX_FloatRect InToOut(const CFX_FloatRect& rect) const;
  CFX_FloatRect OutToIn(const CFX_FloatRect& rect) const;

  CFX_PointF InnerToOuter(const CFX_PointF& point) const;
  CFX_PointF OuterToInner(const CFX_PointF& point) const;
  CFX_FloatRect InnerToOuter(const CFX_FloatRect& rect) const;
  CFX_FloatRect OuterToInner(const CFX_FloatRect& rect) const;

  void OnVK(int32_t nItemIndex, bool bShift, bool bCtrl);
  bool IsValid(int32_t nItemIndex) const;

  void ReArrange(int32_t nItemIndex);
  CFX_FloatRect GetItemRectInternal(int32_t nIndex) const;
  CFX_FloatRect GetContentRectInternal() const;
  void SetMultipleSelect(int32_t nItemIndex, bool bSelected);
  void SetSingleSelect(int32_t nItemIndex);
  void InvalidateItem(int32_t nItemIndex);
  void SelectItems();
  bool IsItemVisible(int32_t nItemIndex) const;
  void SetScrollInfo();
  void SetScrollPosY(float fy);
  void AddItem(const WideString& str);
  WideString GetItemText(int32_t nIndex) const;
  void SetItemSelect(int32_t nIndex, bool bSelected);
  int32_t GetLastSelected() const;
  CFX_PointF GetBTPoint() const {
    return CFX_PointF(m_rcPlate.left, m_rcPlate.top);
  }

  CFX_FloatRect m_rcPlate;
  CFX_FloatRect m_rcContent;
  CFX_PointF m_ptScrollPos;
  float m_fFontSize = 0.0f;

  // For single:
  int32_t m_nSelItem = -1;

  // For multiple:
  SelectState m_SelectState;
  int32_t m_nFootIndex = -1;
  int32_t m_nCaretIndex = -1;
  bool m_bCtrlSel = false;

  bool m_bMultiple = false;
  bool m_bNotifyFlag = false;
  UnownedPtr<NotifyIface> m_pNotify;
  std::vector<std::unique_ptr<Item>> m_ListItems;
  UnownedPtr<IPVT_FontMap> m_pFontMap;
};

#endif  // FPDFSDK_PWL_CPWL_LIST_CTRL_H_
