// 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_PDFWINDOW_PWL_NOTE_H_
#define FPDFSDK_PDFWINDOW_PWL_NOTE_H_

#include "fpdfsdk/pdfwindow/PWL_Button.h"
#include "fpdfsdk/pdfwindow/PWL_Edit.h"
#include "fpdfsdk/pdfwindow/PWL_ListCtrl.h"
#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
#include "fpdfsdk/pdfwindow/PWL_Wnd.h"

class CPWL_Label;
class CPWL_Note;
class CPWL_NoteItem;
class CPWL_Note_CloseBox;
class CPWL_Note_Contents;
class CPWL_Note_Edit;
class CPWL_Note_Icon;
class CPWL_Note_LBBox;
class CPWL_Note_Options;
class CPWL_Note_RBBox;
class IPWL_NoteHandler;
class IPWL_NoteItem;
class IPWL_NoteNotify;
class IPopup_Note;

class IPWL_NoteNotify {
 public:
  virtual ~IPWL_NoteNotify() {}
  virtual void OnNoteMove(const FX_RECT& rtWin) = 0;
  virtual void OnNoteShow(FX_BOOL bShow) = 0;
  virtual void OnNoteActivate(FX_BOOL bActive) = 0;
  virtual void OnNoteClose() = 0;
  virtual void OnItemCreate(IPWL_NoteItem* pItem) = 0;
  virtual void OnItemDelete(IPWL_NoteItem* pItem) = 0;
  virtual void OnSetAuthorName(IPWL_NoteItem* pItem) = 0;
  virtual void OnSetBkColor(IPWL_NoteItem* pItem) = 0;
  virtual void OnSetContents(IPWL_NoteItem* pItem) = 0;
  virtual void OnSetDateTime(IPWL_NoteItem* pItem) = 0;
  virtual void OnSetSubjectName(IPWL_NoteItem* pItem) = 0;
  virtual void OnPopupMenu(int32_t x, int32_t y) = 0;
  virtual void OnPopupMenu(IPWL_NoteItem* pItem, int32_t x, int32_t y) = 0;
};

class IPWL_NoteHandler {
 public:
  virtual ~IPWL_NoteHandler() {}
  virtual void OnNoteColorChanged(const CPWL_Color& color) = 0;
};

class IPWL_NoteItem {
 public:
  virtual ~IPWL_NoteItem() {}
  virtual void SetPrivateData(void* pData) = 0;
  virtual void SetBkColor(const CPWL_Color& color) = 0;
  virtual void SetSubjectName(const CFX_WideString& sName) = 0;
  virtual void SetAuthorName(const CFX_WideString& sName) = 0;
  virtual void SetDateTime(FX_SYSTEMTIME time) = 0;
  virtual void SetContents(const CFX_WideString& sContents) = 0;

  virtual IPWL_NoteItem* CreateSubItem() = 0;
  virtual int32_t CountSubItems() const = 0;
  virtual IPWL_NoteItem* GetSubItems(int32_t index) const = 0;
  virtual void DeleteSubItem(IPWL_NoteItem* pNoteItem) = 0;
  virtual void SetFocus() = 0;

  virtual IPWL_NoteItem* GetParentItem() const = 0;
  virtual void* GetPrivateData() const = 0;
  virtual CFX_WideString GetAuthorName() const = 0;
  virtual CPWL_Color GetBkColor() const = 0;
  virtual CFX_WideString GetContents() const = 0;
  virtual FX_SYSTEMTIME GetDateTime() const = 0;
  virtual CFX_WideString GetSubjectName() const = 0;

  virtual CPWL_Edit* GetEdit() const = 0;
};

class CPWL_Note_Icon : public CPWL_Wnd {
 public:
  CPWL_Note_Icon();
  ~CPWL_Note_Icon() override;

  void SetIconType(int32_t nType);

 protected:
  // CPWL_Wnd
  void DrawThisAppearance(CFX_RenderDevice* pDevice,
                          CFX_Matrix* pUser2Device) override;

 private:
  int32_t m_nType;
};

class CPWL_Note_CloseBox : public CPWL_Button {
 public:
  CPWL_Note_CloseBox();
  ~CPWL_Note_CloseBox() override;

 protected:
  // CPWL_Button
  void DrawThisAppearance(CFX_RenderDevice* pDevice,
                          CFX_Matrix* pUser2Device) override;
  FX_BOOL OnLButtonDown(const CFX_FloatPoint& point, uint32_t nFlag) override;
  FX_BOOL OnLButtonUp(const CFX_FloatPoint& point, uint32_t nFlag) override;

 private:
  FX_BOOL m_bMouseDown;
};

class CPWL_Note_LBBox : public CPWL_Wnd {
 public:
  CPWL_Note_LBBox();
  ~CPWL_Note_LBBox() override;

 protected:
  // CPWL_Wnd
  void DrawThisAppearance(CFX_RenderDevice* pDevice,
                          CFX_Matrix* pUser2Device) override;
};

class CPWL_Note_RBBox : public CPWL_Wnd {
 public:
  CPWL_Note_RBBox();
  ~CPWL_Note_RBBox() override;

 protected:
  // CPWL_Wnd
  void DrawThisAppearance(CFX_RenderDevice* pDevice,
                          CFX_Matrix* pUser2Device) override;
};

class CPWL_Note_Edit : public CPWL_Edit {
 public:
  CPWL_Note_Edit();
  ~CPWL_Note_Edit() override;

  void EnableNotify(FX_BOOL bEnable) { m_bEnableNotify = bEnable; }

  // CPWL_Edit
  FX_FLOAT GetItemLeftMargin() override;
  FX_FLOAT GetItemRightMargin() override;
  FX_FLOAT GetItemHeight(FX_FLOAT fLimitWidth) override;
  void SetText(const FX_WCHAR* csText) override;
  void OnNotify(CPWL_Wnd* pWnd,
                uint32_t msg,
                intptr_t wParam = 0,
                intptr_t lParam = 0) override;
  void RePosChildWnd() override;
  void OnSetFocus() override;
  void OnKillFocus() override;

 private:
  FX_BOOL m_bEnableNotify;
  FX_FLOAT m_fOldItemHeight;
  FX_BOOL m_bSizeChanged;
  FX_FLOAT m_fOldMin;
  FX_FLOAT m_fOldMax;
};

class CPWL_Note_Options : public CPWL_Wnd {
 public:
  CPWL_Note_Options();
  ~CPWL_Note_Options() override;

  CFX_FloatRect GetContentRect() const;
  void SetText(const CFX_WideString& sText);

  // CPWL_Wnd
  void RePosChildWnd() override;
  void CreateChildWnd(const PWL_CREATEPARAM& cp) override;
  void DrawThisAppearance(CFX_RenderDevice* pDevice,
                          CFX_Matrix* pUser2Device) override;
  void SetTextColor(const CPWL_Color& color) override;

 private:
  CPWL_Label* m_pText;
};

class CPWL_Note_Contents : public CPWL_ListCtrl {
 public:
  CPWL_Note_Contents();
  ~CPWL_Note_Contents() override;

  void SetEditFocus(FX_BOOL bLast);
  CPWL_Edit* GetEdit() const;

  void SetText(const CFX_WideString& sText);
  CFX_WideString GetText() const;

  CPWL_NoteItem* CreateSubItem();
  void DeleteSubItem(IPWL_NoteItem* pNoteItem);
  int32_t CountSubItems() const;
  IPWL_NoteItem* GetSubItems(int32_t index) const;

  virtual IPWL_NoteItem* GetHitNoteItem(const CFX_FloatPoint& point);
  void EnableRead(FX_BOOL bEnabled);
  void EnableModify(FX_BOOL bEnabled);

  // CPWL_ListCtrl
  CFX_ByteString GetClassName() const override;
  void OnNotify(CPWL_Wnd* pWnd,
                uint32_t msg,
                intptr_t wParam = 0,
                intptr_t lParam = 0) override;
  FX_BOOL OnLButtonDown(const CFX_FloatPoint& point, uint32_t nFlag) override;
  void CreateChildWnd(const PWL_CREATEPARAM& cp) override;

 private:
  CPWL_Note_Edit* m_pEdit;
};

class CPWL_NoteItem : public CPWL_Wnd, public IPWL_NoteItem {
 public:
  CPWL_NoteItem();
  ~CPWL_NoteItem() override;

  virtual IPWL_NoteItem* GetHitNoteItem(const CFX_FloatPoint& point);
  virtual IPWL_NoteItem* GetFocusedNoteItem() const;

  virtual FX_BOOL IsTopItem() const { return FALSE; }

  virtual void ResetSubjectName(int32_t nItemIndex);
  void EnableRead(FX_BOOL bEnabled);
  void EnableModify(FX_BOOL bEnabled);

  void OnContentsValidate();
  void OnCreateNoteItem();

  // IPWL_NoteItem
  void SetPrivateData(void* pData) override;
  void SetBkColor(const CPWL_Color& color) override;
  void SetSubjectName(const CFX_WideString& sName) override;
  void SetAuthorName(const CFX_WideString& sName) override;
  void SetDateTime(FX_SYSTEMTIME time) override;
  void SetContents(const CFX_WideString& sContents) override;
  IPWL_NoteItem* CreateSubItem() override;
  int32_t CountSubItems() const override;
  IPWL_NoteItem* GetSubItems(int32_t index) const override;
  void DeleteSubItem(IPWL_NoteItem* pNoteItem) override;
  void SetFocus() override { SetNoteFocus(FALSE); }
  IPWL_NoteItem* GetParentItem() const override;
  void* GetPrivateData() const override;
  CFX_WideString GetAuthorName() const override;
  CPWL_Color GetBkColor() const override;
  CFX_WideString GetContents() const override;
  FX_SYSTEMTIME GetDateTime() const override;
  CFX_WideString GetSubjectName() const override;
  CPWL_Edit* GetEdit() const override;

 protected:
  // CPWL_Wnd
  FX_BOOL OnLButtonDown(const CFX_FloatPoint& point, uint32_t nFlag) override;
  FX_BOOL OnRButtonUp(const CFX_FloatPoint& point, uint32_t nFlag) override;
  CFX_ByteString GetClassName() const override;
  void RePosChildWnd() override;
  void CreateChildWnd(const PWL_CREATEPARAM& cp) override;
  void OnNotify(CPWL_Wnd* pWnd,
                uint32_t msg,
                intptr_t wParam = 0,
                intptr_t lParam = 0) override;
  FX_FLOAT GetItemHeight(FX_FLOAT fLimitWidth) override;
  FX_FLOAT GetItemLeftMargin() override;
  FX_FLOAT GetItemRightMargin() override;

  CPWL_NoteItem* CreateNoteItem();
  CPWL_NoteItem* GetParentNoteItem() const;

  void SetNoteFocus(FX_BOOL bLast);
  void PopupNoteItemMenu(const CFX_FloatPoint& point);

  virtual const CPWL_Note* GetNote() const;
  virtual IPWL_NoteNotify* GetNoteNotify() const;

 protected:
  CPWL_Label* m_pSubject;
  CPWL_Label* m_pDateTime;
  CPWL_Note_Contents* m_pContents;

 private:
  void* m_pPrivateData;
  FX_SYSTEMTIME m_dtNote;
  CFX_WideString m_sAuthor;

  FX_FLOAT m_fOldItemHeight;
  FX_BOOL m_bSizeChanged;
  FX_BOOL m_bAllowModify;
};

class CPWL_Note : public CPWL_NoteItem {
 public:
  CPWL_Note(IPopup_Note* pPopupNote,
            IPWL_NoteNotify* pNoteNotify,
            IPWL_NoteHandler* pNoteHandler);
  ~CPWL_Note() override;

  IPWL_NoteItem* Reply();
  void EnableNotify(FX_BOOL bEnabled);
  void SetIconType(int32_t nType);
  void SetOptionsText(const CFX_WideString& sText);
  void EnableRead(FX_BOOL bEnabled);
  void EnableModify(FX_BOOL bEnabled);

  CFX_WideString GetReplyString() const;
  void SetReplyString(const CFX_WideString& str);

  // CPWL_NoteItem
  void SetSubjectName(const CFX_WideString& sName) override;
  void SetAuthorName(const CFX_WideString& sName) override;
  CFX_WideString GetAuthorName() const override;
  void SetBkColor(const CPWL_Color& color) override;
  void ResetSubjectName(int32_t nItemIndex) override {}
  FX_BOOL IsTopItem() const override { return TRUE; }
  const CPWL_Note* GetNote() const override;
  IPWL_NoteNotify* GetNoteNotify() const override;
  FX_BOOL OnLButtonDown(const CFX_FloatPoint& point, uint32_t nFlag) override;
  FX_BOOL OnRButtonUp(const CFX_FloatPoint& point, uint32_t nFlag) override;
  FX_BOOL OnMouseWheel(short zDelta,
                       const CFX_FloatPoint& point,
                       uint32_t nFlag) override;
  void RePosChildWnd() override;
  void CreateChildWnd(const PWL_CREATEPARAM& cp) override;
  void OnNotify(CPWL_Wnd* pWnd,
                uint32_t msg,
                intptr_t wParam = 0,
                intptr_t lParam = 0) override;

 protected:
  FX_BOOL ResetScrollBar();
  void RePosNoteChildren();
  FX_BOOL ScrollBarShouldVisible();

 private:
  CPWL_Label* m_pAuthor;
  CPWL_Note_Icon* m_pIcon;
  CPWL_Note_CloseBox* m_pCloseBox;
  CPWL_Note_LBBox* m_pLBBox;
  CPWL_Note_RBBox* m_pRBBox;
  CPWL_ScrollBar* m_pContentsBar;
  CPWL_Note_Options* m_pOptions;
  IPWL_NoteNotify* m_pNoteNotify;
  FX_BOOL m_bResizing;
  PWL_SCROLL_INFO m_OldScrollInfo;
  FX_BOOL m_bEnableNotify;
  CFX_WideString m_sReplyString;
};

#endif  // FPDFSDK_PDFWINDOW_PWL_NOTE_H_