// 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_CFWL_WIDGET_H_
#define XFA_FWL_CFWL_WIDGET_H_
#include <memory>

#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_system.h"
#include "xfa/fwl/cfwl_event.h"
#include "xfa/fwl/cfwl_themepart.h"
#include "xfa/fwl/cfwl_widgetmgr.h"
#include "xfa/fwl/fwl_widgethit.h"
#include "xfa/fwl/ifwl_widgetdelegate.h"
#include "xfa/fwl/theme/cfwl_widgettp.h"

enum class FWL_Type {
  Unknown = 0,

  Barcode,
  Caret,
  CheckBox,
  ComboBox,
  DateTimePicker,
  Edit,
  Form,
  FormProxy,
  ListBox,
  MonthCalendar,
  PictureBox,
  PushButton,
  ScrollBar,
  SpinButton,
  ToolTip
};

class CFWL_App;
class CFWL_AppImp;
class CFWL_MessageKey;
class CFWL_Widget;
class CFWL_WidgetMgr;
class CFWL_WidgetProperties;
class CXFA_FFWidget;
class IFWL_ThemeProvider;

class CFWL_Widget : public IFWL_WidgetDelegate {
 public:
  ~CFWL_Widget() override;

  virtual FWL_Type GetClassID() const = 0;
  virtual bool IsInstance(const CFX_WideStringC& wsClass) const;
  virtual CFX_RectF GetAutosizedWidgetRect();
  virtual CFX_RectF GetWidgetRect();
  virtual CFX_RectF GetClientRect();
  virtual void ModifyStylesEx(uint32_t dwStylesExAdded,
                              uint32_t dwStylesExRemoved);
  virtual void SetStates(uint32_t dwStates);
  virtual void RemoveStates(uint32_t dwStates);
  virtual void Update() = 0;
  virtual FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy);
  virtual void DrawWidget(CFX_Graphics* pGraphics,
                          const CFX_Matrix* pMatrix) = 0;
  virtual void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider);

  // IFWL_WidgetDelegate.
  void OnProcessMessage(CFWL_Message* pMessage) override;
  void OnProcessEvent(CFWL_Event* pEvent) override;
  void OnDrawWidget(CFX_Graphics* pGraphics,
                    const CFX_Matrix* pMatrix) override;

  void InflateWidgetRect(CFX_RectF& rect);
  void SetWidgetRect(const CFX_RectF& rect);

  void SetParent(CFWL_Widget* pParent);

  CFWL_Widget* GetOwner() { return m_pWidgetMgr->GetOwnerWidget(this); }
  CFWL_Widget* GetOuter() const { return m_pOuter; }

  uint32_t GetStyles() const;
  void ModifyStyles(uint32_t dwStylesAdded, uint32_t dwStylesRemoved);
  uint32_t GetStylesEx() const;
  uint32_t GetStates() const;

  void LockUpdate() { m_iLock++; }
  void UnlockUpdate() {
    if (IsLocked())
      m_iLock--;
  }

  void TransformTo(CFWL_Widget* pWidget, FX_FLOAT& fx, FX_FLOAT& fy);
  CFX_Matrix GetMatrix();
  IFWL_ThemeProvider* GetThemeProvider() const;

  void SetDelegate(IFWL_WidgetDelegate* delegate) { m_pDelegate = delegate; }
  IFWL_WidgetDelegate* GetDelegate() {
    return m_pDelegate ? m_pDelegate : this;
  }
  const IFWL_WidgetDelegate* GetDelegate() const {
    return m_pDelegate ? m_pDelegate : this;
  }

  const CFWL_App* GetOwnerApp() const { return m_pOwnerApp; }
  uint32_t GetEventKey() const { return m_nEventKey; }
  void SetEventKey(uint32_t key) { m_nEventKey = key; }

  CXFA_FFWidget* GetLayoutItem() const { return m_pLayoutItem; }
  void SetLayoutItem(CXFA_FFWidget* pItem) { m_pLayoutItem = pItem; }

  void SetFocus(bool bFocus);
  void RepaintRect(const CFX_RectF& pRect);
  void Repaint();

 protected:
  CFWL_Widget(const CFWL_App* app,
              std::unique_ptr<CFWL_WidgetProperties> properties,
              CFWL_Widget* pOuter);

  bool IsEnabled() const;
  bool IsLocked() const { return m_iLock > 0; }
  bool HasBorder() const;
  CFX_RectF GetEdgeRect();
  FX_FLOAT GetBorderSize(bool bCX);
  CFX_RectF GetRelativeRect();
  IFWL_ThemeProvider* GetAvailableTheme();
  CFX_SizeF CalcTextSize(const CFX_WideString& wsText,
                         IFWL_ThemeProvider* pTheme,
                         bool bMultiLine);
  void CalcTextRect(const CFX_WideString& wsText,
                    IFWL_ThemeProvider* pTheme,
                    uint32_t dwTTOStyles,
                    int32_t iTTOAlign,
                    CFX_RectF& rect);
  void SetGrab(bool bSet);
  void GetPopupPos(FX_FLOAT fMinHeight,
                   FX_FLOAT fMaxHeight,
                   const CFX_RectF& rtAnchor,
                   CFX_RectF& rtPopup);
  void RegisterEventTarget(CFWL_Widget* pEventSource);
  void UnregisterEventTarget();
  void DispatchEvent(CFWL_Event* pEvent);
  void DrawBorder(CFX_Graphics* pGraphics,
                  CFWL_Part iPartBorder,
                  IFWL_ThemeProvider* pTheme,
                  const CFX_Matrix* pMatrix);

  const CFWL_App* const m_pOwnerApp;
  CFWL_WidgetMgr* const m_pWidgetMgr;
  std::unique_ptr<CFWL_WidgetProperties> m_pProperties;
  CFWL_Widget* m_pOuter;
  int32_t m_iLock;

 private:
  CFWL_Widget* GetParent() { return m_pWidgetMgr->GetParentWidget(this); }
  CFX_SizeF GetOffsetFromParent(CFWL_Widget* pParent);

  bool IsVisible() const;
  bool IsOverLapper() const;
  bool IsPopup() const;
  bool IsChild() const;
  CFWL_Widget* GetRootOuter();
  bool GetPopupPosMenu(FX_FLOAT fMinHeight,
                       FX_FLOAT fMaxHeight,
                       const CFX_RectF& rtAnchor,
                       CFX_RectF& rtPopup);
  bool GetPopupPosComboBox(FX_FLOAT fMinHeight,
                           FX_FLOAT fMaxHeight,
                           const CFX_RectF& rtAnchor,
                           CFX_RectF& rtPopup);
  bool GetPopupPosGeneral(FX_FLOAT fMinHeight,
                          FX_FLOAT fMaxHeight,
                          const CFX_RectF& rtAnchor,
                          CFX_RectF& rtPopup);
  bool GetScreenSize(FX_FLOAT& fx, FX_FLOAT& fy);
  void DrawBackground(CFX_Graphics* pGraphics,
                      CFWL_Part iPartBk,
                      IFWL_ThemeProvider* pTheme,
                      const CFX_Matrix* pMatrix);
  void NotifyDriver();
  bool IsParent(CFWL_Widget* pParent);

  CXFA_FFWidget* m_pLayoutItem;
  uint32_t m_nEventKey;
  IFWL_WidgetDelegate* m_pDelegate;  // Not owned.
};

#endif  // XFA_FWL_CFWL_WIDGET_H_
