// 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 <cmath>
#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_pathdata.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/dib/cfx_dibitmap.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_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"
#include "xfa/fxgraphics/cxfa_graphics.h"

namespace {

FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,
                              int32_t iComponents,
                              int32_t iBitsPerComponent) {
  FXDIB_Format dibFormat = FXDIB_Argb;
  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_Rgb32;
      int32_t bpp = iComponents * iBitsPerComponent;
      if (bpp <= 24) {
        dibFormat = FXDIB_Rgb;
      }
    } break;
#ifdef PDF_ENABLE_XFA_PNG
    case FXCODEC_IMAGE_PNG:
#endif  // PDF_ENABLE_XFA_PNG
    default:
      break;
  }
  return dibFormat;
}

bool IsFXCodecErrorStatus(FXCODEC_STATUS status) {
  return (status == FXCODEC_STATUS_ERROR ||
          status == FXCODEC_STATUS_ERR_MEMORY ||
          status == FXCODEC_STATUS_ERR_READ ||
          status == FXCODEC_STATUS_ERR_FLUSH ||
          status == FXCODEC_STATUS_ERR_FORMAT ||
          status == FXCODEC_STATUS_ERR_PARAMS);
}

}  // namespace

void XFA_DrawImage(CXFA_Graphics* 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_PathData 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 = (int32_t)(dibAttr.m_nXDPI * 2.54f);
      dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f);
      break;
    case FXCODEC_RESUNIT_METER:
      dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (float)100 * 2.54f);
      dibAttr.m_nYDPI = (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_DECODE_READY || nFrames == 0)
    return nullptr;

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

  while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
    status = pProgressiveDecoder->ContinueDecode();
    if (IsFXCodecErrorStatus(status))
      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());
}

CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
  if (!pLayoutItem->GetFormNode()->HasCreatedUIWidget())
    return nullptr;

  return GetFFWidget(ToContentLayoutItem(pLayoutItem));
}

CXFA_CalcData::CXFA_CalcData() = default;

CXFA_CalcData::~CXFA_CalcData() = default;

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

CXFA_FFWidget::~CXFA_FFWidget() = default;

const CFWL_App* CXFA_FFWidget::GetFWLApp() {
  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_RectCached))
    RecacheWidgetRect();
  return m_WidgetRect;
}

const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const {
  GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_RectCached);
  m_WidgetRect = GetLayoutItem()->GetRect(false);
  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(uint32_t dwAdded, uint32_t 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(CXFA_Graphics* 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() {
  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());

  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(CXFA_Graphics* pGS,
                               CXFA_Box* box,
                               const CFX_RectF& rtBorder,
                               const CFX_Matrix& matrix) {
  if (box)
    box->Draw(pGS, rtBorder, matrix, false);
}

void CXFA_FFWidget::DrawBorderWithFlag(CXFA_Graphics* 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(uint32_t dwFlags,
                                             const CFX_PointF& point,
                                             FWL_MouseCommand command) {
  return false;
}

bool CXFA_FFWidget::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnMouseWheel(uint32_t dwFlags,
                                 const CFX_PointF& point,
                                 const CFX_Vector& delta) {
  return false;
}

bool CXFA_FFWidget::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
  return false;
}

bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
  RetainPtr<CXFA_ContentLayoutItem> retainer(m_pLayoutItem.Get());

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

  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) {
  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
  RetainPtr<CXFA_ContentLayoutItem> retainer(m_pLayoutItem.Get());

  ObservedPtr<CXFA_FFWidget> pNewWatched(pNewWidget);
  GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_Focused);
  EventKillFocus();
  if (!pNewWidget)
    return true;

  if (!pNewWatched)
    return false;

  // OnKillFocus event may remove |pNewWidget|.
  CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
  if (pParent && !pParent->IsAncestorOf(pNewWidget)) {
    if (!pParent->OnKillFocus(pNewWidget))
      return false;
  }
  return !!pNewWatched;
}

bool CXFA_FFWidget::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) {
  return false;
}

bool CXFA_FFWidget::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) {
  return false;
}

bool CXFA_FFWidget::OnChar(uint32_t dwChar, uint32_t 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 {};
}

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

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) {
  IXFA_DocEnvironment* pDocEnvironment = GetDoc()->GetDocEnvironment();
  if (!pDocEnvironment)
    return;

  pDocEnvironment->DisplayCaret(this, bVisible, pRtAnchor);
}

void CXFA_FFWidget::GetBorderColorAndThickness(FX_ARGB* cr, float* fWidth) {
  ASSERT(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();
}

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

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

void CXFA_FFWidget::EventKillFocus() {
  CXFA_ContentLayoutItem* pItem = GetLayoutItem();
  if (pItem->TestStatusBits(XFA_WidgetStatus_Access)) {
    pItem->ClearStatusBits(XFA_WidgetStatus_Access);
    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_ButtonDown);
}

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