// 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_FWL_WIDGETMGRIMP_H_
#define XFA_FWL_CORE_FWL_WIDGETMGRIMP_H_

#include "xfa/include/fwl/core/fwl_widgetmgr.h"

class IFWL_Widget;
class IFWL_AdapterWidgetMgr;
class CFWL_WidgetMgrDelegate;
class IFWL_AdapterNative;

class CFWL_WidgetMgrItem {
 public:
  CFWL_WidgetMgrItem()
      : pParent(NULL),
        pOwner(NULL),
        pChild(NULL),
        pPrevious(NULL),
        pNext(NULL),
        pWidget(NULL),
        pOffscreen(NULL),
        iRedrawCounter(0)
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
        ,
        bOutsideChanged(FALSE)
#endif
  {
  }
  ~CFWL_WidgetMgrItem() {
    if (pOffscreen) {
      delete pOffscreen;
      pOffscreen = NULL;
    }
  }
  CFWL_WidgetMgrItem* pParent;
  CFWL_WidgetMgrItem* pOwner;
  CFWL_WidgetMgrItem* pChild;
  CFWL_WidgetMgrItem* pPrevious;
  CFWL_WidgetMgrItem* pNext;
  IFWL_Widget* pWidget;
  CFX_Graphics* pOffscreen;
  int32_t iRedrawCounter;
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
  FX_BOOL bOutsideChanged;
#endif
};

class CFWL_WidgetMgr : public IFWL_WidgetMgr {
 public:
  CFWL_WidgetMgr(IFWL_AdapterNative* pAdapterNative);
  ~CFWL_WidgetMgr() override;

  // IFWL_WidgetMgr:
  int32_t CountWidgets(IFWL_Widget* pParent = NULL) override;
  IFWL_Widget* GetWidget(int32_t nIndex, IFWL_Widget* pParent = NULL) override;
  IFWL_Widget* GetWidget(IFWL_Widget* pWidget,
                         FWL_WGTRELATION eRelation) override;
  int32_t GetWidgetIndex(IFWL_Widget* pWidget) override;
  FX_BOOL SetWidgetIndex(IFWL_Widget* pWidget, int32_t nIndex) override;
  FWL_ERR RepaintWidget(IFWL_Widget* pWidget,
                        const CFX_RectF* pRect = NULL) override;
  FX_DWORD GetCapability() override { return m_dwCapability; }

  void AddWidget(IFWL_Widget* pWidget);
  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);
  FX_BOOL IsChild(IFWL_Widget* pChild, IFWL_Widget* pParent);
  FWL_ERR CreateWidget_Native(IFWL_Widget* pWidget);
  FWL_ERR DestroyWidget_Native(IFWL_Widget* pWidget);
  FWL_ERR GetWidgetRect_Native(IFWL_Widget* pWidget, CFX_RectF& rect);
  FWL_ERR SetWidgetRect_Native(IFWL_Widget* pWidget, const CFX_RectF& rect);
  FWL_ERR SetWidgetPosition_Native(IFWL_Widget* pWidget,
                                   FX_FLOAT fx,
                                   FX_FLOAT fy);
  FWL_ERR SetWidgetIcon_Native(IFWL_Widget* pWidget,
                               const CFX_DIBitmap* pIcon,
                               FX_BOOL bBig);
  FWL_ERR SetWidgetCaption_Native(IFWL_Widget* pWidget,
                                  const CFX_WideStringC& wsCaption);
  FWL_ERR SetBorderRegion_Native(IFWL_Widget* pWidget, CFX_Path* pPath);
  FWL_ERR ShowWidget_Native(IFWL_Widget* pWidget);
  FWL_ERR HideWidget_Native(IFWL_Widget* pWidget);
  FWL_ERR SetNormal_Native(IFWL_Widget* pWidget);
  FWL_ERR SetMaximize_Native(IFWL_Widget* pWidget);
  FWL_ERR SetMinimize_Native(IFWL_Widget* pWidget);
  FX_BOOL CheckMessage_Native();
  FWL_ERR DispatchMessage_Native();
  FX_BOOL IsIdleMessage_Native();
  FWL_ERR Exit_Native(int32_t iExitCode);
  FWL_ERR CreateWidgetWithNativeId_Native(IFWL_Widget* pWidget, void* vp);
  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, FX_BOOL& bFind);
  int32_t CountRadioButtonGroup(IFWL_Widget* pFirst);
  IFWL_Widget* GetSiblingRadioButton(IFWL_Widget* pWidget, FX_BOOL bNext);
  IFWL_Widget* GetRadioButtonGroupHeader(IFWL_Widget* pRadioButton);
  void GetSameGroupRadioButton(IFWL_Widget* pRadioButton, CFX_PtrArray& group);
  IFWL_Widget* GetDefaultButton(IFWL_Widget* pParent);
  void AddRedrawCounts(IFWL_Widget* pWidget);
  void ResetRedrawCounts(IFWL_Widget* pWidget);
  IFWL_AdapterWidgetMgr* GetAdapterWidgetMgr() { return m_pAdapter; }
  CFWL_WidgetMgrDelegate* GetDelegate() { return m_pDelegate; }
  CFWL_WidgetMgrItem* GetWidgetMgrItem(IFWL_Widget* pWidget);
  FX_BOOL IsThreadEnabled();
  FX_BOOL IsFormDisabled();
  FX_BOOL GetAdapterPopupPos(IFWL_Widget* pWidget,
                             FX_FLOAT fMinHeight,
                             FX_FLOAT fMaxHeight,
                             const CFX_RectF& rtAnchor,
                             CFX_RectF& rtPopup);

 protected:
  int32_t TravelWidgetMgr(CFWL_WidgetMgrItem* pParent,
                          int32_t* pIndex,
                          CFWL_WidgetMgrItem* pItem,
                          IFWL_Widget** pWidget = NULL);
  FX_BOOL IsAbleNative(IFWL_Widget* pWidget);
  CFX_MapPtrToPtr m_mapWidgetItem;
  IFWL_AdapterWidgetMgr* m_pAdapter;
  CFWL_WidgetMgrDelegate* m_pDelegate;
  friend class CFWL_WidgetMgrDelegate;
  FX_DWORD m_dwCapability;
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
  CFX_RectF m_rtScreen;
#endif
};

class CFWL_WidgetMgrDelegate : public IFWL_WidgetMgrDelegate {
 public:
  CFWL_WidgetMgrDelegate(CFWL_WidgetMgr* pWidgetMgr);
  ~CFWL_WidgetMgrDelegate() override {}

  // IFWL_WidgetMgrDelegate:
  FWL_ERR OnSetCapability(
      FX_DWORD dwCapability = FWL_WGTMGR_DisableThread) override;
  int32_t OnProcessMessageToForm(CFWL_Message* pMessage) override;
  FWL_ERR OnDrawWidget(IFWL_Widget* pWidget,
                       CFX_Graphics* pGraphics,
                       const CFX_Matrix* pMatrix) override;

 protected:
  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);
  FX_BOOL IsNeedRepaint(IFWL_Widget* pWidget,
                        CFX_Matrix* pMatrix,
                        const CFX_RectF& rtDirty);
  FX_BOOL bUseOffscreenDirect(IFWL_Widget* pWidget);

  CFWL_WidgetMgr* m_pWidgetMgr;
};

#endif  // XFA_FWL_CORE_FWL_WIDGETMGRIMP_H_
