// 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/fxfa/cxfa_ffwidget.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "core/fxcodec/fx_codec.h"
#include "core/fxcodec/progressive_decoder.h"
#include "core/fxcrt/maybe_owned.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_path.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "third_party/base/check.h"
#include "xfa/fgas/graphics/cfgas_gegraphics.h"
#include "xfa/fwl/fwl_widgethit.h"
#include "xfa/fxfa/cxfa_eventparam.h"
#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/cxfa_ffdocview.h"
#include "xfa/fxfa/cxfa_ffpageview.h"
#include "xfa/fxfa/cxfa_ffwidgethandler.h"
#include "xfa/fxfa/cxfa_imagerenderer.h"
#include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_border.h"
#include "xfa/fxfa/parser/cxfa_box.h"
#include "xfa/fxfa/parser/cxfa_edge.h"
#include "xfa/fxfa/parser/cxfa_image.h"
#include "xfa/fxfa/parser/cxfa_margin.h"
#include "xfa/fxfa/parser/cxfa_node.h"

namespace {

FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,
                              int32_t iComponents,
                              int32_t iBitsPerComponent) {
  FXDIB_Format dibFormat = FXDIB_Format::kArgb;
  switch (type) {
    case FXCODEC_IMAGE_JPG:
#ifdef PDF_ENABLE_XFA_BMP
    case FXCODEC_IMAGE_BMP:
#endif  // PDF_ENABLE_XFA_BMP
#ifdef PDF_ENABLE_XFA_TIFF
    case FXCODEC_IMAGE_TIFF:
#endif  // PDF_ENABLE_XFA_TIFF
    {
      dibFormat = FXDIB_Format::kRgb32;
      int32_t bpp = iComponents * iBitsPerComponent;
      if (bpp <= 24) {
        dibFormat = FXDIB_Format::kRgb;
      }
    } break;
#ifdef PDF_ENABLE_XFA_PNG
    case FXCODEC_IMAGE_PNG:
#endif  // PDF_ENABLE_XFA_PNG
    default:
      break;
  }
  return dibFormat;
}

}  // namespace

void XFA_DrawImage(CFGAS_GEGraphics* pGS,
                   const CFX_RectF& rtImage,
                   const CFX_Matrix& matrix,
                   const RetainPtr<CFX_DIBitmap>& pDIBitmap,
                   XFA_AttributeValue iAspect,
                   const CFX_Size& dpi,
                   XFA_AttributeValue iHorzAlign,
                   XFA_AttributeValue iVertAlign) {
  if (rtImage.IsEmpty())
    return;
  if (!pDIBitmap || !pDIBitmap->GetBuffer())
    return;

  CFX_RectF rtFit(rtImage.TopLeft(),
                  XFA_UnitPx2Pt(pDIBitmap->GetWidth(), dpi.width),
                  XFA_UnitPx2Pt(pDIBitmap->GetHeight(), dpi.height));
  switch (iAspect) {
    case XFA_AttributeValue::Fit: {
      float f1 = rtImage.height / rtFit.height;
      float f2 = rtImage.width / rtFit.width;
      f1 = std::min(f1, f2);
      rtFit.height = rtFit.height * f1;
      rtFit.width = rtFit.width * f1;
      break;
    }
    case XFA_AttributeValue::Height: {
      float f1 = rtImage.height / rtFit.height;
      rtFit.height = rtImage.height;
      rtFit.width = f1 * rtFit.width;
      break;
    }
    case XFA_AttributeValue::None:
      rtFit.height = rtImage.height;
      rtFit.width = rtImage.width;
      break;
    case XFA_AttributeValue::Width: {
      float f1 = rtImage.width / rtFit.width;
      rtFit.width = rtImage.width;
      rtFit.height = rtFit.height * f1;
      break;
    }
    case XFA_AttributeValue::Actual:
    default:
      break;
  }

  if (iHorzAlign == XFA_AttributeValue::Center)
    rtFit.left += (rtImage.width - rtFit.width) / 2;
  else if (iHorzAlign == XFA_AttributeValue::Right)
    rtFit.left = rtImage.right() - rtFit.width;

  if (iVertAlign == XFA_AttributeValue::Middle)
    rtFit.top += (rtImage.height - rtFit.height) / 2;
  else if (iVertAlign == XFA_AttributeValue::Bottom)
    rtFit.top = rtImage.bottom() - rtImage.height;

  CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
  CFX_RenderDevice::StateRestorer restorer(pRenderDevice);
  CFX_Path path;
  path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top);
  pRenderDevice->SetClip_PathFill(&path, &matrix,
                                  CFX_FillRenderOptions::WindingOptions());

  CFX_Matrix mtImage(1, 0, 0, -1, 0, 1);
  mtImage.Concat(
      CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top));
  mtImage.Concat(matrix);

  CXFA_ImageRenderer imageRender(pRenderDevice, pDIBitmap, mtImage);
  if (!imageRender.Start()) {
    return;
  }
  while (imageRender.Continue())
    continue;
}

RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer(
    const RetainPtr<IFX_SeekableReadStream>& pImageFileRead,
    FXCODEC_IMAGE_TYPE type,
    int32_t& iImageXDpi,
    int32_t& iImageYDpi) {
  auto pProgressiveDecoder = std::make_unique<ProgressiveDecoder>();

  CFX_DIBAttribute dibAttr;
  pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false);
  switch (dibAttr.m_wDPIUnit) {
    case FXCODEC_RESUNIT_CENTIMETER:
      dibAttr.m_nXDPI = static_cast<int32_t>(dibAttr.m_nXDPI * 2.54f);
      dibAttr.m_nYDPI = static_cast<int32_t>(dibAttr.m_nYDPI * 2.54f);
      break;
    case FXCODEC_RESUNIT_METER:
      dibAttr.m_nXDPI =
          static_cast<int32_t>(dibAttr.m_nXDPI / (float)100 * 2.54f);
      dibAttr.m_nYDPI =
          static_cast<int32_t>(dibAttr.m_nYDPI / (float)100 * 2.54f);
      break;
    default:
      break;
  }
  iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96);
  iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96);
  if (pProgressiveDecoder->GetWidth() <= 0 ||
      pProgressiveDecoder->GetHeight() <= 0) {
    return nullptr;
  }

  type = pProgressiveDecoder->GetType();
  int32_t iComponents = pProgressiveDecoder->GetNumComponents();
  int32_t iBpc = pProgressiveDecoder->GetBPC();
  FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc);
  RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  pBitmap->Create(pProgressiveDecoder->GetWidth(),
                  pProgressiveDecoder->GetHeight(), dibFormat);
  pBitmap->Clear(0xffffffff);

  size_t nFrames;
  FXCODEC_STATUS status;
  std::tie(status, nFrames) = pProgressiveDecoder->GetFrames();
  if (status != FXCODEC_STATUS::kDecodeReady || nFrames == 0)
    return nullptr;

  status = pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(),
                                            pBitmap->GetHeight());
  if (status == FXCODEC_STATUS::kError)
    return nullptr;

  while (status == FXCODEC_STATUS::kDecodeToBeContinued) {
    status = pProgressiveDecoder->ContinueDecode();
    if (status == FXCODEC_STATUS::kError)
      return nullptr;
  }

  return pBitmap;
}

void XFA_RectWithoutMargin(CFX_RectF* rt, const CXFA_Margin* margin) {
  if (!margin)
    return;

  rt->Deflate(margin->GetLeftInset(), margin->GetTopInset(),
              margin->GetRightInset(), margin->GetBottomInset());
}

// static
CXFA_FFWidget* CXFA_FFWidget::FromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
  if (!pLayoutItem->GetFormNode()->HasCreatedUIWidget())
    return nullptr;

  return GetFFWidget(ToContentLayoutItem(pLayoutItem));
}

CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node) : m_pNode(node) {}

CXFA_FFWidget::~CXFA_FFWidget() = default;

void CXFA_FFWidget::Trace(cppgc::Visitor* visitor) const {
  visitor->Trace(m_pLayoutItem);
  visitor->Trace(m_pDocView);
  visitor->Trace(m_pPageView);
  visitor->Trace(m_pNode);
}

CFWL_App* CXFA_FFWidget::GetFWLApp() const {
  return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp();
}

CXFA_FFWidget* CXFA_FFWidget::GetNextFFWidget() const {
  return GetFFWidget(GetLayoutItem()->GetNext());
}

const CFX_RectF& CXFA_FFWidget::GetWidgetRect() const {
  if (!GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kRectCached))
    RecacheWidgetRect();
  return m_WidgetRect;
}

const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const {
  GetLayoutItem()->SetStatusBits(XFA_WidgetStatus::kRectCached);
  m_WidgetRect = GetLayoutItem()->GetAbsoluteRect();
  return m_WidgetRect;
}

CFX_RectF CXFA_FFWidget::GetRectWithoutRotate() {
  CFX_RectF rtWidget = GetWidgetRect();
  float fValue = 0;
  switch (m_pNode->GetRotate()) {
    case 90:
      rtWidget.top = rtWidget.bottom();
      fValue = rtWidget.width;
      rtWidget.width = rtWidget.height;
      rtWidget.height = fValue;
      break;
    case 180:
      rtWidget.left = rtWidget.right();
      rtWidget.top = rtWidget.bottom();
      break;
    case 270:
      rtWidget.left = rtWidget.right();
      fValue = rtWidget.width;
      rtWidget.width = rtWidget.height;
      rtWidget.height = fValue;
      break;
  }
  return rtWidget;
}

void CXFA_FFWidget::ModifyStatus(Mask<XFA_WidgetStatus> dwAdded,
                                 Mask<XFA_WidgetStatus> dwRemoved) {
  GetLayoutItem()->ClearStatusBits(dwRemoved);
  GetLayoutItem()->SetStatusBits(dwAdded);
}

CXFA_FFField* CXFA_FFWidget::AsField() {
  return nullptr;
}

CFX_RectF CXFA_FFWidget::GetBBox(FocusOption focus) {
  if (focus == kDrawFocus || !m_pPageView)
    return CFX_RectF();
  return m_pPageView->GetPageViewRect();
}

void CXFA_FFWidget::RenderWidget(CFGAS_GEGraphics* pGS,
                                 const CFX_Matrix& matrix,
                                 HighlightOption highlight) {
  if (!HasVisibleStatus())
    return;

  CXFA_Border* border = m_pNode->GetBorderIfExists();
  if (!border)
    return;

  CFX_RectF rtBorder = GetRectWithoutRotate();
  CXFA_Margin* margin = border->GetMarginIfExists();
  XFA_RectWithoutMargin(&rtBorder, margin);
  rtBorder.Normalize();
  DrawBorder(pGS, border, rtBorder, matrix);
}

bool CXFA_FFWidget::IsLoaded() {
  return !!m_pPageView;
}

bool CXFA_FFWidget::LoadWidget() {
  PerformLayout();
  return true;
}

bool CXFA_FFWidget::PerformLayout() {
  RecacheWidgetRect();
  return true;
}

bool CXFA_FFWidget::UpdateFWLData() {
  return false;
}

void CXFA_FFWidget::UpdateWidgetProperty() {}

bool CXFA_FFWidget::HasEventUnderHandler(XFA_EVENTTYPE eEventType,
                                         CXFA_FFWidgetHandler* pHandler) {
  CXFA_Node* pNode = GetNode();
  return pNode->IsWidgetReady() && pHandler->HasEvent(pNode, eEventType);
}

bool CXFA_FFWidget::ProcessEventUnderHandler(CXFA_EventParam* params,
                                             CXFA_FFWidgetHandler* pHandler) {
  CXFA_Node* pNode = GetNode();
  if (!pNode->IsWidgetReady())
    return false;

  params->m_pTarget = pNode;
  return pHandler->ProcessEvent(pNode, params) == XFA_EventError::kSuccess;
}

void CXFA_FFWidget::DrawBorder(CFGAS_GEGraphics* pGS,
                               CXFA_Box* box,
                               const CFX_RectF& rtBorder,
                               const CFX_Matrix& matrix) {
  if (box)
    box->Draw(pGS, rtBorder, matrix, false);
}

void CXFA_FFWidget::DrawBorderWithFlag(CFGAS_GEGraphics* pGS,
                                       CXFA_Box* box,
                                       const CFX_RectF& rtBorder,
                                       const CFX_Matrix& matrix,
                                       bool forceRound) {
  if (box)
    box->Draw(pGS, rtBorder, matrix, forceRound);
}

void CXFA_FFWidget::InvalidateRect() {
  CFX_RectF rtWidget = GetBBox(kDoNotDrawFocus);
  rtWidget.Inflate(2, 2);
  m_pDocView->InvalidateRect(m_pPageView.Get(), rtWidget);
}

bool CXFA_FFWidget::OnMouseEnter() {
  return false;
}

bool CXFA_FFWidget::OnMouseExit() {
  return false;
}

bool CXFA_FFWidget::AcceptsFocusOnButtonDown(
    Mask<XFA_FWL_KeyFlag> dwFlags,
    const CFX_PointF& point,
    CFWL_MessageMouse::MouseCommand command) {
  return false;
}

bool CXFA_FFWidget::OnLButtonDown(Mask<XFA_FWL_KeyFlag> dwFlags,
                                  const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnLButtonUp(Mask<XFA_FWL_KeyFlag> dwFlags,
                                const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnLButtonDblClk(Mask<XFA_FWL_KeyFlag> dwFlags,
                                    const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnMouseMove(Mask<XFA_FWL_KeyFlag> dwFlags,
                                const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnMouseWheel(Mask<XFA_FWL_KeyFlag> dwFlags,
                                 const CFX_PointF& point,
                                 const CFX_Vector& delta) {
  return false;
}

bool CXFA_FFWidget::OnRButtonDown(Mask<XFA_FWL_KeyFlag> dwFlags,
                                  const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnRButtonUp(Mask<XFA_FWL_KeyFlag> dwFlags,
                                const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnRButtonDblClk(Mask<XFA_FWL_KeyFlag> dwFlags,
                                    const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
  CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
  if (pParent && !pParent->IsAncestorOf(pOldWidget)) {
    if (!pParent->OnSetFocus(pOldWidget))
      return false;
  }
  GetLayoutItem()->SetStatusBits(XFA_WidgetStatus::kFocused);

  CXFA_EventParam eParam;
  eParam.m_eType = XFA_EVENT_Enter;
  eParam.m_pTarget = m_pNode.Get();
  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Enter, &eParam);
  return true;
}

bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) {
  GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus::kFocused);
  EventKillFocus();
  if (!pNewWidget)
    return true;

  CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
  if (pParent && !pParent->IsAncestorOf(pNewWidget)) {
    if (!pParent->OnKillFocus(pNewWidget))
      return false;
  }
  return true;
}

bool CXFA_FFWidget::OnKeyDown(XFA_FWL_VKEYCODE dwKeyCode,
                              Mask<XFA_FWL_KeyFlag> dwFlags) {
  return false;
}

bool CXFA_FFWidget::OnKeyUp(XFA_FWL_VKEYCODE dwKeyCode,
                            Mask<XFA_FWL_KeyFlag> dwFlags) {
  return false;
}

bool CXFA_FFWidget::OnChar(uint32_t dwChar, Mask<XFA_FWL_KeyFlag> dwFlags) {
  return false;
}

FWL_WidgetHit CXFA_FFWidget::HitTest(const CFX_PointF& point) {
  return FWL_WidgetHit::Unknown;
}

bool CXFA_FFWidget::CanUndo() {
  return false;
}

bool CXFA_FFWidget::CanRedo() {
  return false;
}

bool CXFA_FFWidget::CanCopy() {
  return false;
}

bool CXFA_FFWidget::CanCut() {
  return false;
}

bool CXFA_FFWidget::CanPaste() {
  return false;
}

bool CXFA_FFWidget::CanSelectAll() {
  return false;
}

bool CXFA_FFWidget::CanDelete() {
  return CanCut();
}

bool CXFA_FFWidget::CanDeSelect() {
  return CanCopy();
}

bool CXFA_FFWidget::Undo() {
  return false;
}

bool CXFA_FFWidget::Redo() {
  return false;
}

Optional<WideString> CXFA_FFWidget::Copy() {
  return pdfium::nullopt;
}

Optional<WideString> CXFA_FFWidget::Cut() {
  return pdfium::nullopt;
}

bool CXFA_FFWidget::Paste(const WideString& wsPaste) {
  return false;
}

void CXFA_FFWidget::SelectAll() {}

void CXFA_FFWidget::Delete() {}

void CXFA_FFWidget::DeSelect() {}

WideString CXFA_FFWidget::GetText() {
  return WideString();
}

FormFieldType CXFA_FFWidget::GetFormFieldType() {
  return FormFieldType::kXFA;
}

CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) {
  CFX_Matrix mt = GetRotateMatrix();
  if (mt.IsIdentity())
    return point;

  return mt.GetInverse().Transform(point);
}

CFX_Matrix CXFA_FFWidget::GetRotateMatrix() {
  int32_t iRotate = m_pNode->GetRotate();
  if (!iRotate)
    return CFX_Matrix();

  CFX_RectF rcWidget = GetRectWithoutRotate();
  CFX_Matrix mt;
  switch (iRotate) {
    case 90:
      mt.a = 0;
      mt.b = -1;
      mt.c = 1;
      mt.d = 0;
      mt.e = rcWidget.left - rcWidget.top;
      mt.f = rcWidget.left + rcWidget.top;
      break;
    case 180:
      mt.a = -1;
      mt.b = 0;
      mt.c = 0;
      mt.d = -1;
      mt.e = rcWidget.left * 2;
      mt.f = rcWidget.top * 2;
      break;
    case 270:
      mt.a = 0;
      mt.b = 1;
      mt.c = -1;
      mt.d = 0;
      mt.e = rcWidget.left + rcWidget.top;
      mt.f = rcWidget.top - rcWidget.left;
      break;
  }
  return mt;
}

void CXFA_FFWidget::DisplayCaret(bool bVisible, const CFX_RectF* pRtAnchor) {
  GetDoc()->DisplayCaret(this, bVisible, pRtAnchor);
}

void CXFA_FFWidget::GetBorderColorAndThickness(FX_ARGB* cr, float* fWidth) {
  DCHECK(GetNode()->IsWidgetReady());
  CXFA_Border* borderUI = GetNode()->GetUIBorder();
  if (!borderUI)
    return;

  CXFA_Edge* edge = borderUI->GetEdgeIfExists(0);
  if (!edge)
    return;

  *cr = edge->GetColor();
  *fWidth = edge->GetThickness();
}

bool CXFA_FFWidget::IsLayoutRectEmpty() {
  CFX_RectF rtLayout = GetRectWithoutRotate();
  return rtLayout.width < 0.1f && rtLayout.height < 0.1f;
}

CXFA_LayoutItem* CXFA_FFWidget::GetParent() {
  CXFA_Node* pParentNode = m_pNode->GetParent();
  if (!pParentNode)
    return nullptr;

  CXFA_LayoutProcessor* layout = GetDocView()->GetLayoutProcessor();
  return layout->GetLayoutItem(pParentNode);
}

bool CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) {
  if (!pWidget)
    return false;

  CXFA_Node* pChildNode = pWidget->GetNode();
  while (pChildNode) {
    if (pChildNode == m_pNode)
      return true;

    pChildNode = pChildNode->GetParent();
  }
  return false;
}

bool CXFA_FFWidget::PtInActiveRect(const CFX_PointF& point) {
  return GetWidgetRect().Contains(point);
}

CXFA_FFDoc* CXFA_FFWidget::GetDoc() {
  return m_pDocView->GetDoc();
}

CXFA_FFApp* CXFA_FFWidget::GetApp() {
  return GetDoc()->GetApp();
}

CXFA_FFApp::CallbackIface* CXFA_FFWidget::GetAppProvider() {
  return GetApp()->GetAppProvider();
}

bool CXFA_FFWidget::HasVisibleStatus() const {
  return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kVisible);
}

void CXFA_FFWidget::EventKillFocus() {
  CXFA_ContentLayoutItem* pItem = GetLayoutItem();
  if (pItem->TestStatusBits(XFA_WidgetStatus::kAccess)) {
    pItem->ClearStatusBits(XFA_WidgetStatus::kAccess);
    return;
  }
  CXFA_EventParam eParam;
  eParam.m_eType = XFA_EVENT_Exit;
  eParam.m_pTarget = m_pNode.Get();
  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Exit, &eParam);
}

bool CXFA_FFWidget::IsButtonDown() {
  return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kButtonDown);
}

void CXFA_FFWidget::SetButtonDown(bool bSet) {
  CXFA_ContentLayoutItem* pItem = GetLayoutItem();
  if (bSet)
    pItem->SetStatusBits(XFA_WidgetStatus::kButtonDown);
  else
    pItem->ClearStatusBits(XFA_WidgetStatus::kButtonDown);
}
