// Copyright 2014 The PDFium Authors
// 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

#include "xfa/fwl/cfwl_widget.h"

#include <algorithm>
#include <utility>
#include <vector>

#include "core/fxcrt/check.h"
#include "v8/include/cppgc/visitor.h"
#include "xfa/fde/cfde_textout.h"
#include "xfa/fwl/cfwl_app.h"
#include "xfa/fwl/cfwl_combobox.h"
#include "xfa/fwl/cfwl_event.h"
#include "xfa/fwl/cfwl_eventmouse.h"
#include "xfa/fwl/cfwl_messagekey.h"
#include "xfa/fwl/cfwl_messagekillfocus.h"
#include "xfa/fwl/cfwl_messagemouse.h"
#include "xfa/fwl/cfwl_messagemousewheel.h"
#include "xfa/fwl/cfwl_messagesetfocus.h"
#include "xfa/fwl/cfwl_notedriver.h"
#include "xfa/fwl/cfwl_themebackground.h"
#include "xfa/fwl/cfwl_themepart.h"
#include "xfa/fwl/cfwl_themetext.h"
#include "xfa/fwl/cfwl_widgetmgr.h"
#include "xfa/fwl/ifwl_themeprovider.h"

namespace pdfium {

namespace {

constexpr float kCalcHeight = 2048.0f;
constexpr float kCalcWidth = 2048.0f;
constexpr float kCalcMultiLineDefWidth = 120.0f;

}  // namespace

CFWL_Widget::CFWL_Widget(CFWL_App* app,
                         const Properties& properties,
                         CFWL_Widget* pOuter)
    : m_Properties(properties),
      m_pFWLApp(app),
      m_pWidgetMgr(app->GetWidgetMgr()),
      m_pOuter(pOuter) {
  m_pWidgetMgr->InsertWidget(m_pOuter, this);
}

CFWL_Widget::~CFWL_Widget() = default;

void CFWL_Widget::PreFinalize() {
  CHECK(!IsLocked());  // Prefer hard stop to UaF.
  NotifyDriver();
  m_pWidgetMgr->RemoveWidget(this);
}

void CFWL_Widget::Trace(cppgc::Visitor* visitor) const {
  visitor->Trace(m_pAdapterIface);
  visitor->Trace(m_pFWLApp);
  visitor->Trace(m_pWidgetMgr);
  visitor->Trace(m_pDelegate);
  visitor->Trace(m_pOuter);
}

bool CFWL_Widget::IsForm() const {
  return false;
}

CFX_RectF CFWL_Widget::GetAutosizedWidgetRect() {
  return CFX_RectF();
}

CFX_RectF CFWL_Widget::GetWidgetRect() {
  return m_WidgetRect;
}

void CFWL_Widget::InflateWidgetRect(CFX_RectF& rect) {
  if (!HasBorder())
    return;

  float fBorder = GetCXBorderSize();
  rect.Inflate(fBorder, fBorder);
}

void CFWL_Widget::SetWidgetRect(const CFX_RectF& rect) {
  m_WidgetRect = rect;
}

CFX_RectF CFWL_Widget::GetClientRect() {
  return GetEdgeRect();
}

void CFWL_Widget::ModifyStyles(uint32_t dwStylesAdded,
                               uint32_t dwStylesRemoved) {
  m_Properties.m_dwStyles &= ~dwStylesRemoved;
  m_Properties.m_dwStyles |= dwStylesAdded;
}

void CFWL_Widget::ModifyStyleExts(uint32_t dwStyleExtsAdded,
                                  uint32_t dwStyleExtsRemoved) {
  m_Properties.m_dwStyleExts &= ~dwStyleExtsRemoved;
  m_Properties.m_dwStyleExts |= dwStyleExtsAdded;
}

static void NotifyHideChildWidget(CFWL_WidgetMgr* widgetMgr,
                                  CFWL_Widget* widget,
                                  CFWL_NoteDriver* noteDriver) {
  CFWL_Widget* child = widgetMgr->GetFirstChildWidget(widget);
  while (child) {
    noteDriver->NotifyTargetHide(child);
    NotifyHideChildWidget(widgetMgr, child, noteDriver);
    child = widgetMgr->GetNextSiblingWidget(child);
  }
}

void CFWL_Widget::SetStates(uint32_t dwStates) {
  m_Properties.m_dwStates |= dwStates;
  if (IsVisible())
    return;

  CFWL_NoteDriver* noteDriver = GetFWLApp()->GetNoteDriver();
  noteDriver->NotifyTargetHide(this);

  CFWL_WidgetMgr* widgetMgr = GetFWLApp()->GetWidgetMgr();
  CFWL_Widget* child = widgetMgr->GetFirstChildWidget(this);
  while (child) {
    noteDriver->NotifyTargetHide(child);
    NotifyHideChildWidget(widgetMgr, child, noteDriver);
    child = widgetMgr->GetNextSiblingWidget(child);
  }
}

void CFWL_Widget::RemoveStates(uint32_t dwStates) {
  m_Properties.m_dwStates &= ~dwStates;
}

FWL_WidgetHit CFWL_Widget::HitTest(const CFX_PointF& point) {
  if (GetClientRect().Contains(point))
    return FWL_WidgetHit::Client;
  if (HasBorder() && GetRelativeRect().Contains(point))
    return FWL_WidgetHit::Border;
  return FWL_WidgetHit::Unknown;
}

CFX_PointF CFWL_Widget::TransformTo(CFWL_Widget* pWidget,
                                    const CFX_PointF& point) {
  CFX_SizeF szOffset;
  if (IsParent(pWidget)) {
    szOffset = GetOffsetFromParent(pWidget);
  } else {
    szOffset = pWidget->GetOffsetFromParent(this);
    szOffset.width = -szOffset.width;
    szOffset.height = -szOffset.height;
  }
  return point + CFX_PointF(szOffset.width, szOffset.height);
}

CFX_Matrix CFWL_Widget::GetMatrix() const {
  CFWL_Widget* parent = GetParent();
  std::vector<CFWL_Widget*> parents;
  while (parent) {
    parents.push_back(parent);
    parent = parent->GetParent();
  }

  CFX_Matrix matrix;
  for (size_t i = parents.size(); i >= 2; i--) {
    CFX_RectF rect = parents[i - 2]->GetWidgetRect();
    matrix.TranslatePrepend(rect.left, rect.top);
  }
  return matrix;
}

IFWL_ThemeProvider* CFWL_Widget::GetThemeProvider() const {
  return GetFWLApp()->GetThemeProvider();
}

bool CFWL_Widget::IsEnabled() const {
  return (m_Properties.m_dwStates & FWL_STATE_WGT_Disabled) == 0;
}

bool CFWL_Widget::HasBorder() const {
  return !!(m_Properties.m_dwStyles & FWL_STYLE_WGT_Border);
}

bool CFWL_Widget::IsVisible() const {
  return !(m_Properties.m_dwStates & FWL_STATE_WGT_Invisible);
}

bool CFWL_Widget::IsOverLapper() const {
  return (m_Properties.m_dwStyles & FWL_STYLE_WGT_WindowTypeMask) ==
         FWL_STYLE_WGT_OverLapper;
}

bool CFWL_Widget::IsPopup() const {
  return !!(m_Properties.m_dwStyles & FWL_STYLE_WGT_Popup);
}

bool CFWL_Widget::IsChild() const {
  return !!(m_Properties.m_dwStyles & FWL_STYLE_WGT_Child);
}

CFWL_Widget* CFWL_Widget::GetOutmost() const {
  CFWL_Widget* pOuter = const_cast<CFWL_Widget*>(this);
  while (pOuter->GetOuter())
    pOuter = pOuter->GetOuter();
  return pOuter;
}

CFX_RectF CFWL_Widget::GetEdgeRect() const {
  CFX_RectF rtEdge(0, 0, m_WidgetRect.width, m_WidgetRect.height);
  if (HasBorder())
    rtEdge.Deflate(GetCXBorderSize(), GetCYBorderSize());
  return rtEdge;
}

float CFWL_Widget::GetCXBorderSize() const {
  return GetThemeProvider()->GetCXBorderSize();
}

float CFWL_Widget::GetCYBorderSize() const {
  return GetThemeProvider()->GetCYBorderSize();
}

CFX_RectF CFWL_Widget::GetRelativeRect() const {
  return CFX_RectF(0, 0, m_WidgetRect.width, m_WidgetRect.height);
}

CFX_SizeF CFWL_Widget::CalcTextSize(const WideString& wsText, bool bMultiLine) {
  CFWL_ThemeText calPart(CFWL_ThemePart::Part::kNone, this, nullptr);
  calPart.m_wsText = wsText;
  if (bMultiLine)
    calPart.m_dwTTOStyles.line_wrap_ = true;
  else
    calPart.m_dwTTOStyles.single_line_ = true;

  calPart.m_iTTOAlign = FDE_TextAlignment::kTopLeft;
  float fWidth = bMultiLine ? kCalcMultiLineDefWidth : kCalcWidth;
  CFX_RectF rect(0, 0, fWidth, kCalcHeight);
  GetThemeProvider()->CalcTextRect(calPart, &rect);
  return CFX_SizeF(rect.width, rect.height);
}

void CFWL_Widget::CalcTextRect(const WideString& wsText,
                               const FDE_TextStyle& dwTTOStyles,
                               FDE_TextAlignment iTTOAlign,
                               CFX_RectF* pRect) {
  CFWL_ThemeText calPart(CFWL_ThemePart::Part::kNone, this, nullptr);
  calPart.m_wsText = wsText;
  calPart.m_dwTTOStyles = dwTTOStyles;
  calPart.m_iTTOAlign = iTTOAlign;
  GetThemeProvider()->CalcTextRect(calPart, pRect);
}

void CFWL_Widget::SetGrab(bool bSet) {
  CFWL_NoteDriver* pDriver = GetFWLApp()->GetNoteDriver();
  pDriver->SetGrab(bSet ? this : nullptr);
}

void CFWL_Widget::UnregisterEventTarget() {
  CFWL_NoteDriver* pNoteDriver = GetFWLApp()->GetNoteDriver();
  pNoteDriver->UnregisterEventTarget(this);
}

void CFWL_Widget::DispatchEvent(CFWL_Event* pEvent) {
  if (m_pOuter) {
    m_pOuter->GetDelegate()->OnProcessEvent(pEvent);
    return;
  }
  CFWL_NoteDriver* pNoteDriver = GetFWLApp()->GetNoteDriver();
  pNoteDriver->SendEvent(pEvent);
}

void CFWL_Widget::RepaintRect(const CFX_RectF& pRect) {
  m_pWidgetMgr->RepaintWidget(this, pRect);
}

void CFWL_Widget::DrawBackground(CFGAS_GEGraphics* pGraphics,
                                 CFWL_ThemePart::Part iPartBk,
                                 const CFX_Matrix& mtMatrix) {
  CFWL_ThemeBackground param(iPartBk, this, pGraphics);
  param.m_matrix = mtMatrix;
  param.m_PartRect = GetRelativeRect();
  GetThemeProvider()->DrawBackground(param);
}

void CFWL_Widget::DrawBorder(CFGAS_GEGraphics* pGraphics,
                             CFWL_ThemePart::Part iPartBorder,
                             const CFX_Matrix& matrix) {
  CFWL_ThemeBackground param(iPartBorder, this, pGraphics);
  param.m_matrix = matrix;
  param.m_PartRect = GetRelativeRect();
  GetThemeProvider()->DrawBackground(param);
}

void CFWL_Widget::NotifyDriver() {
  CFWL_NoteDriver* pDriver = GetFWLApp()->GetNoteDriver();
  pDriver->NotifyTargetDestroy(this);
}

CFX_SizeF CFWL_Widget::GetOffsetFromParent(CFWL_Widget* pParent) {
  if (pParent == this)
    return CFX_SizeF();

  CFX_SizeF szRet(m_WidgetRect.left, m_WidgetRect.top);
  CFWL_WidgetMgr* pWidgetMgr = GetFWLApp()->GetWidgetMgr();
  CFWL_Widget* pDstWidget = GetParent();
  while (pDstWidget && pDstWidget != pParent) {
    CFX_RectF rtDst = pDstWidget->GetWidgetRect();
    szRet += CFX_SizeF(rtDst.left, rtDst.top);
    pDstWidget = pWidgetMgr->GetParentWidget(pDstWidget);
  }
  return szRet;
}

bool CFWL_Widget::IsParent(CFWL_Widget* pParent) {
  CFWL_Widget* pUpWidget = GetParent();
  while (pUpWidget) {
    if (pUpWidget == pParent)
      return true;
    pUpWidget = pUpWidget->GetParent();
  }
  return false;
}

void CFWL_Widget::OnProcessMessage(CFWL_Message* pMessage) {
  CFWL_Widget* pWidget = pMessage->GetDstTarget();
  if (!pWidget)
    return;

  switch (pMessage->GetType()) {
    case CFWL_Message::Type::kMouse: {
      CFWL_MessageMouse* pMsgMouse = static_cast<CFWL_MessageMouse*>(pMessage);
      CFWL_EventMouse evt(pWidget, pWidget, pMsgMouse->m_dwCmd);
      pWidget->DispatchEvent(&evt);
      break;
    }
    default:
      break;
  }
}

void CFWL_Widget::OnProcessEvent(CFWL_Event* pEvent) {}

CFWL_Widget::ScopedUpdateLock::ScopedUpdateLock(CFWL_Widget* widget)
    : widget_(widget) {
  widget_->LockUpdate();
}

CFWL_Widget::ScopedUpdateLock::~ScopedUpdateLock() {
  widget_->UnlockUpdate();
}

}  // namespace pdfium
