// 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_CFWL_WIDGETMGR_H_
#define XFA_FWL_CORE_CFWL_WIDGETMGR_H_

#include <map>
#include <memory>

#include "core/fxcrt/fx_system.h"
#include "xfa/fwl/core/fwl_error.h"
#include "xfa/fxgraphics/cfx_graphics.h"

#define FWL_WGTMGR_DisableThread 0x00000001
#define FWL_WGTMGR_DisableForm 0x00000002

class CFWL_Message;
class CXFA_FFApp;
class CXFA_FWLAdapterWidgetMgr;
class CFX_Graphics;
class CFX_Matrix;
class IFWL_Widget;

class CFWL_WidgetMgrItem {
 public:
  CFWL_WidgetMgrItem();
  explicit CFWL_WidgetMgrItem(IFWL_Widget* widget);
  ~CFWL_WidgetMgrItem();

  CFWL_WidgetMgrItem* pParent;
  CFWL_WidgetMgrItem* pOwner;
  CFWL_WidgetMgrItem* pChild;
  CFWL_WidgetMgrItem* pPrevious;
  CFWL_WidgetMgrItem* pNext;
  IFWL_Widget* const pWidget;
  std::unique_ptr<CFX_Graphics> pOffscreen;
  int32_t iRedrawCounter;
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
  bool bOutsideChanged;
#endif
};

class IFWL_WidgetMgrDelegate {
 public:
  virtual void OnSetCapability(
      uint32_t dwCapability = FWL_WGTMGR_DisableThread) = 0;
  virtual void OnProcessMessageToForm(CFWL_Message* pMessage) = 0;
  virtual void OnDrawWidget(IFWL_Widget* pWidget,
                            CFX_Graphics* pGraphics,
                            const CFX_Matrix* pMatrix) = 0;
};

class CFWL_WidgetMgr : public IFWL_WidgetMgrDelegate {
 public:
  explicit CFWL_WidgetMgr(CXFA_FFApp* pAdapterNative);
  ~CFWL_WidgetMgr();

  // IFWL_WidgetMgrDelegate
  void OnSetCapability(
      uint32_t dwCapability = FWL_WGTMGR_DisableThread) override;
  void OnProcessMessageToForm(CFWL_Message* pMessage) override;
  void OnDrawWidget(IFWL_Widget* pWidget,
                    CFX_Graphics* pGraphics,
                    const CFX_Matrix* pMatrix) override;

  IFWL_Widget* GetParentWidget(IFWL_Widget* pWidget) const;
  IFWL_Widget* GetOwnerWidget(IFWL_Widget* pWidget) const;
  IFWL_Widget* GetNextSiblingWidget(IFWL_Widget* pWidget) const;
  IFWL_Widget* GetFirstChildWidget(IFWL_Widget* pWidget) const;
  IFWL_Widget* GetSystemFormWidget(IFWL_Widget* pWidget) const;

  void RepaintWidget(IFWL_Widget* pWidget, const CFX_RectF* pRect = nullptr);

  void InsertWidget(IFWL_Widget* pParent,
                    IFWL_Widget* pChild,
                    int32_t nIndex = -1);
  void RemoveWidget(IFWL_Widget* pWidget);
  void SetOwner(IFWL_Widget* pOwner, IFWL_Widget* pOwned);
  void SetParent(IFWL_Widget* pParent, IFWL_Widget* pChild);

  void SetWidgetRect_Native(IFWL_Widget* pWidget, const CFX_RectF& rect);

  IFWL_Widget* GetWidgetAtPoint(IFWL_Widget* pParent, FX_FLOAT fx, FX_FLOAT fy);

  void NotifySizeChanged(IFWL_Widget* pForm, FX_FLOAT fx, FX_FLOAT fy);

  IFWL_Widget* NextTab(IFWL_Widget* parent, IFWL_Widget* focus, bool& bFind);

  void GetSameGroupRadioButton(IFWL_Widget* pRadioButton,
                               CFX_ArrayTemplate<IFWL_Widget*>& group) const;
  IFWL_Widget* GetDefaultButton(IFWL_Widget* pParent) const;
  void AddRedrawCounts(IFWL_Widget* pWidget);

  bool IsFormDisabled() const {
    return !!(m_dwCapability & FWL_WGTMGR_DisableForm);
  }

  void GetAdapterPopupPos(IFWL_Widget* pWidget,
                          FX_FLOAT fMinHeight,
                          FX_FLOAT fMaxHeight,
                          const CFX_RectF& rtAnchor,
                          CFX_RectF& rtPopup) const;

 private:
  IFWL_Widget* GetFirstSiblingWidget(IFWL_Widget* pWidget) const;
  IFWL_Widget* GetPriorSiblingWidget(IFWL_Widget* pWidget) const;
  IFWL_Widget* GetLastChildWidget(IFWL_Widget* pWidget) const;
  CFWL_WidgetMgrItem* GetWidgetMgrItem(IFWL_Widget* pWidget) const;

  void SetWidgetIndex(IFWL_Widget* pWidget, int32_t nIndex);

  int32_t CountRadioButtonGroup(IFWL_Widget* pFirst) const;
  IFWL_Widget* GetRadioButtonGroupHeader(IFWL_Widget* pRadioButton) const;

  void ResetRedrawCounts(IFWL_Widget* pWidget);

  bool IsThreadEnabled() const {
    return !(m_dwCapability & FWL_WGTMGR_DisableThread);
  }

  void DrawChild(IFWL_Widget* pParent,
                 const CFX_RectF& rtClip,
                 CFX_Graphics* pGraphics,
                 const CFX_Matrix* pMatrix);
  CFX_Graphics* DrawWidgetBefore(IFWL_Widget* pWidget,
                                 CFX_Graphics* pGraphics,
                                 const CFX_Matrix* pMatrix);
  void DrawWidgetAfter(IFWL_Widget* pWidget,
                       CFX_Graphics* pGraphics,
                       CFX_RectF& rtClip,
                       const CFX_Matrix* pMatrix);
  bool IsNeedRepaint(IFWL_Widget* pWidget,
                     CFX_Matrix* pMatrix,
                     const CFX_RectF& rtDirty);
  bool UseOffscreenDirect(IFWL_Widget* pWidget) const;

  bool IsAbleNative(IFWL_Widget* pWidget) const;

  uint32_t m_dwCapability;
  std::map<IFWL_Widget*, std::unique_ptr<CFWL_WidgetMgrItem>> m_mapWidgetItem;
  CXFA_FWLAdapterWidgetMgr* const m_pAdapter;
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
  CFX_RectF m_rtScreen;
#endif
};

#endif  // XFA_FWL_CORE_CFWL_WIDGETMGR_H_
