// 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

#include "xfa/fwl/cfwl_widgetmgr.h"

#include "build/build_config.h"
#include "third_party/base/check.h"
#include "xfa/fwl/cfwl_app.h"
#include "xfa/fwl/cfwl_message.h"
#include "xfa/fwl/cfwl_notedriver.h"

CFWL_WidgetMgr::CFWL_WidgetMgr(AdapterIface* pAdapter, CFWL_App* pApp)
    : m_pAdapter(pAdapter), m_pApp(pApp) {
  DCHECK(m_pAdapter);
  m_mapWidgetItem[nullptr] = cppgc::MakeGarbageCollected<Item>(
      pApp->GetHeap()->GetAllocationHandle(), nullptr);
}

CFWL_WidgetMgr::~CFWL_WidgetMgr() = default;

void CFWL_WidgetMgr::Trace(cppgc::Visitor* visitor) const {
  visitor->Trace(m_pApp);
  visitor->Trace(m_pAdapter);
  for (auto& item : m_mapWidgetItem)
    visitor->Trace(item.second);
}

CFWL_Widget* CFWL_WidgetMgr::GetParentWidget(const CFWL_Widget* pWidget) const {
  Item* pItem = GetWidgetMgrItem(pWidget);
  if (!pItem)
    return nullptr;

  Item* pParent = pItem->GetParent();
  return pParent ? pParent->pWidget : nullptr;
}

CFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(CFWL_Widget* pWidget) const {
  Item* pItem = GetWidgetMgrItem(pWidget);
  if (!pItem)
    return nullptr;

  Item* pSibling = pItem->GetPrevSibling();
  return pSibling ? pSibling->pWidget : nullptr;
}

CFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(CFWL_Widget* pWidget) const {
  Item* pItem = GetWidgetMgrItem(pWidget);
  if (!pItem)
    return nullptr;

  Item* pSibling = pItem->GetNextSibling();
  return pSibling ? pSibling->pWidget : nullptr;
}

CFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(CFWL_Widget* pWidget) const {
  Item* pItem = GetWidgetMgrItem(pWidget);
  if (!pItem)
    return nullptr;

  Item* pChild = pItem->GetFirstChild();
  return pChild ? pChild->pWidget : nullptr;
}

CFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(CFWL_Widget* pWidget) const {
  Item* pItem = GetWidgetMgrItem(pWidget);
  if (!pItem)
    return nullptr;

  Item* pChild = pItem->GetLastChild();
  return pChild ? pChild->pWidget : nullptr;
}

void CFWL_WidgetMgr::RepaintWidget(CFWL_Widget* pWidget,
                                   const CFX_RectF& rect) {
  CFWL_Widget* pNative = pWidget;
  CFX_RectF transformedRect = rect;
  CFWL_Widget* pOuter = pWidget->GetOuter();
  while (pOuter) {
    CFX_RectF rtTemp = pNative->GetWidgetRect();
    transformedRect.left += rtTemp.left;
    transformedRect.top += rtTemp.top;
    pNative = pOuter;
    pOuter = pOuter->GetOuter();
  }
  m_pAdapter->RepaintWidget(pNative);
}

void CFWL_WidgetMgr::InsertWidget(CFWL_Widget* pParent, CFWL_Widget* pChild) {
  Item* pParentItem = GetWidgetMgrItem(pParent);
  if (!pParentItem) {
    pParentItem = CreateWidgetMgrItem(pParent);
    GetWidgetMgrRootItem()->AppendLastChild(pParentItem);
  }
  Item* pChildItem = GetWidgetMgrItem(pChild);
  if (!pChildItem)
    pChildItem = CreateWidgetMgrItem(pChild);
  pParentItem->AppendLastChild(pChildItem);
}

void CFWL_WidgetMgr::RemoveWidget(CFWL_Widget* pWidget) {
  DCHECK(pWidget);
  Item* pItem = GetWidgetMgrItem(pWidget);
  if (!pItem)
    return;

  while (pItem->GetFirstChild())
    RemoveWidget(pItem->GetFirstChild()->pWidget);

  pItem->RemoveSelfIfParented();
  m_mapWidgetItem.erase(pWidget);
}

CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent,
                                              const CFX_PointF& point) const {
  if (!parent)
    return nullptr;

  CFWL_Widget* child = GetLastChildWidget(parent);
  while (child) {
    if (child->IsVisible()) {
      CFX_PointF pos = parent->GetMatrix().GetInverse().Transform(point);
      CFX_RectF bounds = child->GetWidgetRect();
      if (bounds.Contains(pos)) {
        pos -= bounds.TopLeft();
        return GetWidgetAtPoint(child, pos);
      }
    }
    child = GetPriorSiblingWidget(child);
  }
  return parent;
}

CFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(CFWL_Widget* pParent) const {
  if ((pParent->GetClassID() == FWL_Type::PushButton) &&
      (pParent->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
    return pParent;
  }

  CFWL_Widget* child = GetFirstChildWidget(pParent);
  while (child) {
    if ((child->GetClassID() == FWL_Type::PushButton) &&
        (child->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
      return child;
    }
    if (CFWL_Widget* find = GetDefaultButton(child))
      return find;

    child = GetNextSiblingWidget(child);
  }
  return nullptr;
}

CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrRootItem() const {
  return GetWidgetMgrItem(nullptr);
}

CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrItem(
    const CFWL_Widget* pWidget) const {
  auto it = m_mapWidgetItem.find(pWidget);
  return it != m_mapWidgetItem.end() ? it->second : nullptr;
}

CFWL_WidgetMgr::Item* CFWL_WidgetMgr::CreateWidgetMgrItem(
    CFWL_Widget* pWidget) {
  auto* pItem = cppgc::MakeGarbageCollected<Item>(
      m_pApp->GetHeap()->GetAllocationHandle(), pWidget);
  m_mapWidgetItem[pWidget] = pItem;
  return pItem;
}

void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget,
                                        float fMinHeight,
                                        float fMaxHeight,
                                        const CFX_RectF& rtAnchor,
                                        CFX_RectF* pPopupRect) const {
  m_pAdapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor,
                          pPopupRect);
}

void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) {
  CFWL_Widget* pDstWidget = pMessage->GetDstTarget();
  if (!pDstWidget)
    return;

  CFWL_NoteDriver* pNoteDriver = pDstWidget->GetFWLApp()->GetNoteDriver();
  pNoteDriver->ProcessMessage(pMessage);
}

void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget,
                                  CFGAS_GEGraphics* pGraphics,
                                  const CFX_Matrix& matrix) {
  if (!pWidget || !pGraphics)
    return;

  pWidget->GetDelegate()->OnDrawWidget(pGraphics, matrix);

  CFX_RectF clipBounds = pGraphics->GetClipRect();
  if (!clipBounds.IsEmpty())
    DrawChildren(pWidget, clipBounds, pGraphics, &matrix);
}

void CFWL_WidgetMgr::DrawChildren(CFWL_Widget* parent,
                                  const CFX_RectF& rtClip,
                                  CFGAS_GEGraphics* pGraphics,
                                  const CFX_Matrix* pMatrix) {
  if (!parent)
    return;

  CFWL_Widget* pNextChild = GetFirstChildWidget(parent);
  while (pNextChild) {
    CFWL_Widget* child = pNextChild;
    pNextChild = GetNextSiblingWidget(child);
    if (!child->IsVisible())
      continue;

    CFX_RectF rtWidget = child->GetWidgetRect();
    if (rtWidget.IsEmpty())
      continue;

    CFX_Matrix widgetMatrix;
    CFX_RectF clipBounds(rtWidget);
    if (pMatrix)
      widgetMatrix.Concat(*pMatrix);

    widgetMatrix.TranslatePrepend(rtWidget.left, rtWidget.top);

    if (IFWL_WidgetDelegate* pDelegate = child->GetDelegate())
      pDelegate->OnDrawWidget(pGraphics, widgetMatrix);

    DrawChildren(child, clipBounds, pGraphics, &widgetMatrix);
  }
}

CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget) : pWidget(widget) {}

CFWL_WidgetMgr::Item::~Item() = default;

void CFWL_WidgetMgr::Item::Trace(cppgc::Visitor* visitor) const {
  GCedTreeNode<Item>::Trace(visitor);
  visitor->Trace(pWidget);
}
