// 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 "fpdfsdk/formfiller/cffl_formfield.h"

#include <utility>

#include "constants/form_flags.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fxge/cfx_renderdevice.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cffl_privatedata.h"
#include "third_party/base/check.h"

CFFL_FormField::CFFL_FormField(CPDFSDK_FormFillEnvironment* pFormFillEnv,
                               CPDFSDK_Widget* pWidget)
    : m_pFormFillEnv(pFormFillEnv), m_pWidget(pWidget) {
  DCHECK(m_pFormFillEnv);
}

CFFL_FormField::~CFFL_FormField() {
  DestroyWindows();
}

void CFFL_FormField::DestroyWindows() {
  while (!m_Maps.empty()) {
    auto it = m_Maps.begin();
    std::unique_ptr<CPWL_Wnd> pWnd = std::move(it->second);
    m_Maps.erase(it);
    pWnd->InvalidateProvider(this);
    pWnd->Destroy();
  }
}

FX_RECT CFFL_FormField::GetViewBBox(CPDFSDK_PageView* pPageView) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, false);
  CFX_FloatRect rcAnnot =
      pWnd ? PWLtoFFL(pWnd->GetWindowRect()) : m_pWidget->GetRect();
  CFX_FloatRect rcFocus = GetFocusBox(pPageView);

  CFX_FloatRect rcWin = rcAnnot;
  if (!rcFocus.IsEmpty())
    rcWin.Union(rcFocus);
  if (!rcWin.IsEmpty()) {
    rcWin.Inflate(1, 1);
    rcWin.Normalize();
  }

  return rcWin.GetOuterRect();
}

void CFFL_FormField::OnDraw(CPDFSDK_PageView* pPageView,
                            CPDFSDK_Annot* pAnnot,
                            CFX_RenderDevice* pDevice,
                            const CFX_Matrix& mtUser2Device) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, false);
  if (pWnd) {
    pWnd->DrawAppearance(pDevice, GetCurMatrix() * mtUser2Device);
    return;
  }

  CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot);
  if (!CFFL_InteractiveFormFiller::IsVisible(pWidget))
    return;

  pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, nullptr);
}

void CFFL_FormField::OnDrawDeactive(CPDFSDK_PageView* pPageView,
                                    CPDFSDK_Annot* pAnnot,
                                    CFX_RenderDevice* pDevice,
                                    const CFX_Matrix& mtUser2Device) {
  ToCPDFSDKWidget(pAnnot)->DrawAppearance(pDevice, mtUser2Device,
                                          CPDF_Annot::Normal, nullptr);
}

void CFFL_FormField::OnMouseEnter(CPDFSDK_PageView* pPageView) {}

void CFFL_FormField::OnMouseExit(CPDFSDK_PageView* pPageView) {
  m_pTimer.reset();
  DCHECK(m_pWidget);
}

bool CFFL_FormField::OnLButtonDown(CPDFSDK_PageView* pPageView,
                                   CPDFSDK_Annot* pAnnot,
                                   uint32_t nFlags,
                                   const CFX_PointF& point) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, true);
  if (!pWnd)
    return false;

  m_bValid = true;
  FX_RECT rect = GetViewBBox(pPageView);
  InvalidateRect(rect);
  if (!rect.Contains(static_cast<int>(point.x), static_cast<int>(point.y)))
    return false;
  return pWnd->OnLButtonDown(nFlags, FFLtoPWL(point));
}

bool CFFL_FormField::OnLButtonUp(CPDFSDK_PageView* pPageView,
                                 CPDFSDK_Annot* pAnnot,
                                 uint32_t nFlags,
                                 const CFX_PointF& point) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, false);
  if (!pWnd)
    return false;

  InvalidateRect(GetViewBBox(pPageView));
  pWnd->OnLButtonUp(nFlags, FFLtoPWL(point));
  return true;
}

bool CFFL_FormField::OnLButtonDblClk(CPDFSDK_PageView* pPageView,
                                     uint32_t nFlags,
                                     const CFX_PointF& point) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, false);
  if (!pWnd)
    return false;

  pWnd->OnLButtonDblClk(nFlags, FFLtoPWL(point));
  return true;
}

bool CFFL_FormField::OnMouseMove(CPDFSDK_PageView* pPageView,
                                 uint32_t nFlags,
                                 const CFX_PointF& point) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, false);
  if (!pWnd)
    return false;

  pWnd->OnMouseMove(nFlags, FFLtoPWL(point));
  return true;
}

bool CFFL_FormField::OnMouseWheel(CPDFSDK_PageView* pPageView,
                                  uint32_t nFlags,
                                  const CFX_PointF& point,
                                  const CFX_Vector& delta) {
  if (!IsValid())
    return false;

  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, true);
  return pWnd && pWnd->OnMouseWheel(nFlags, FFLtoPWL(point), delta);
}

bool CFFL_FormField::OnRButtonDown(CPDFSDK_PageView* pPageView,
                                   uint32_t nFlags,
                                   const CFX_PointF& point) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, true);
  return pWnd && pWnd->OnRButtonDown(nFlags, FFLtoPWL(point));
}

bool CFFL_FormField::OnRButtonUp(CPDFSDK_PageView* pPageView,
                                 uint32_t nFlags,
                                 const CFX_PointF& point) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, false);
  return pWnd && pWnd->OnRButtonUp(nFlags, FFLtoPWL(point));
}

bool CFFL_FormField::OnKeyDown(uint32_t nKeyCode, uint32_t nFlags) {
  if (!IsValid())
    return false;

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd && pWnd->OnKeyDown(nKeyCode, nFlags);
}

bool CFFL_FormField::OnChar(CPDFSDK_Annot* pAnnot,
                            uint32_t nChar,
                            uint32_t nFlags) {
  if (!IsValid())
    return false;

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd && pWnd->OnChar(nChar, nFlags);
}

bool CFFL_FormField::SetIndexSelected(int index, bool selected) {
  return false;
}

bool CFFL_FormField::IsIndexSelected(int index) {
  return false;
}

WideString CFFL_FormField::GetText() {
  if (!IsValid())
    return WideString();

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd ? pWnd->GetText() : WideString();
}

WideString CFFL_FormField::GetSelectedText() {
  if (!IsValid())
    return WideString();

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd ? pWnd->GetSelectedText() : WideString();
}

void CFFL_FormField::ReplaceSelection(const WideString& text) {
  if (!IsValid())
    return;

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  if (!pWnd)
    return;

  pWnd->ReplaceSelection(text);
}

bool CFFL_FormField::SelectAllText() {
  if (!IsValid())
    return false;

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd && pWnd->SelectAllText();
}

bool CFFL_FormField::CanUndo() {
  if (!IsValid())
    return false;

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd && pWnd->CanUndo();
}

bool CFFL_FormField::CanRedo() {
  if (!IsValid())
    return false;

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd && pWnd->CanRedo();
}

bool CFFL_FormField::Undo() {
  if (!IsValid())
    return false;

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd && pWnd->Undo();
}

bool CFFL_FormField::Redo() {
  if (!IsValid())
    return false;

  CPWL_Wnd* pWnd = GetPWLWindow(GetCurPageView(), false);
  return pWnd && pWnd->Redo();
}

void CFFL_FormField::SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag) {
  CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot);
  IPDF_Page* pPage = pWidget->GetPage();
  CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(pPage, true);
  if (CPWL_Wnd* pWnd = GetPWLWindow(pPageView, true))
    pWnd->SetFocus();

  m_bValid = true;
  InvalidateRect(GetViewBBox(pPageView));
}

void CFFL_FormField::KillFocusForAnnot(uint32_t nFlag) {
  if (!IsValid())
    return;

  CPDFSDK_PageView* pPageView =
      m_pFormFillEnv->GetPageView(m_pWidget->GetPage(), false);
  if (!pPageView || !CommitData(pPageView, nFlag))
    return;
  if (CPWL_Wnd* pWnd = GetPWLWindow(pPageView, false))
    pWnd->KillFocus();

  bool bDestroyPWLWindow;
  switch (m_pWidget->GetFieldType()) {
    case FormFieldType::kPushButton:
    case FormFieldType::kCheckBox:
    case FormFieldType::kRadioButton:
      bDestroyPWLWindow = true;
      break;
    default:
      bDestroyPWLWindow = false;
      break;
  }
  EscapeFiller(pPageView, bDestroyPWLWindow);
}

bool CFFL_FormField::IsValid() const {
  return m_bValid;
}

CPWL_Wnd::CreateParams CFFL_FormField::GetCreateParam() {
  CPWL_Wnd::CreateParams cp;
  cp.pProvider.Reset(this);
  cp.rcRectWnd = GetPDFAnnotRect();

  uint32_t dwCreateFlags = PWS_BORDER | PWS_BACKGROUND | PWS_VISIBLE;
  uint32_t dwFieldFlag = m_pWidget->GetFieldFlags();
  if (dwFieldFlag & pdfium::form_flags::kReadOnly)
    dwCreateFlags |= PWS_READONLY;

  Optional<FX_COLORREF> color = m_pWidget->GetFillColor();
  if (color.has_value())
    cp.sBackgroundColor = CFX_Color(color.value());
  color = m_pWidget->GetBorderColor();
  if (color.has_value())
    cp.sBorderColor = CFX_Color(color.value());

  cp.sTextColor = CFX_Color(CFX_Color::Type::kGray, 0);

  color = m_pWidget->GetTextColor();
  if (color.has_value())
    cp.sTextColor = CFX_Color(color.value());

  cp.fFontSize = m_pWidget->GetFontSize();
  cp.dwBorderWidth = m_pWidget->GetBorderWidth();

  cp.nBorderStyle = m_pWidget->GetBorderStyle();
  switch (cp.nBorderStyle) {
    case BorderStyle::kDash:
      cp.sDash = CPWL_Dash(3, 3, 0);
      break;
    case BorderStyle::kBeveled:
    case BorderStyle::kInset:
      cp.dwBorderWidth *= 2;
      break;
    default:
      break;
  }

  if (cp.fFontSize <= 0)
    dwCreateFlags |= PWS_AUTOFONTSIZE;

  cp.dwFlags = dwCreateFlags;
  cp.pTimerHandler.Reset(m_pFormFillEnv->GetTimerHandler());
  cp.pSystemHandler = m_pFormFillEnv->GetSysHandler();
  return cp;
}

CPWL_Wnd* CFFL_FormField::GetPWLWindow(CPDFSDK_PageView* pPageView, bool bNew) {
  DCHECK(pPageView);
  auto it = m_Maps.find(pPageView);
  if (it == m_Maps.end()) {
    if (!bNew)
      return nullptr;

    CPWL_Wnd::CreateParams cp = GetCreateParam();
    // TODO(tsepez): maybe pass widget's value age as 4th arg.
    auto pPrivateData = std::make_unique<CFFL_PrivateData>(
        m_pWidget.Get(), pPageView, m_pWidget->GetAppearanceAge(), 0);
    m_Maps[pPageView] = NewPWLWindow(cp, std::move(pPrivateData));
    return m_Maps[pPageView].get();
  }

  CPWL_Wnd* pWnd = it->second.get();
  if (!bNew)
    return pWnd;

  const auto* pPrivateData =
      static_cast<const CFFL_PrivateData*>(pWnd->GetAttachedData());
  if (pPrivateData->AppearanceAgeEquals(m_pWidget->GetAppearanceAge()))
    return pWnd;

  return ResetPWLWindow(pPageView,
                        pPrivateData->ValueAgeEquals(m_pWidget->GetValueAge()));
}

void CFFL_FormField::DestroyPWLWindow(CPDFSDK_PageView* pPageView) {
  auto it = m_Maps.find(pPageView);
  if (it == m_Maps.end())
    return;

  std::unique_ptr<CPWL_Wnd> pWnd = std::move(it->second);
  m_Maps.erase(it);
  pWnd->Destroy();
}

CFX_Matrix CFFL_FormField::GetWindowMatrix(
    const IPWL_SystemHandler::PerWindowData* pAttached) {
  const auto* pPrivateData = static_cast<const CFFL_PrivateData*>(pAttached);
  if (!pPrivateData)
    return CFX_Matrix();

  CPDFSDK_PageView* pPageView = pPrivateData->GetPageView();
  if (!pPageView)
    return CFX_Matrix();

  return GetCurMatrix() * pPageView->GetCurrentMatrix();
}

CFX_Matrix CFFL_FormField::GetCurMatrix() {
  CFX_Matrix mt;
  CFX_FloatRect rcDA = m_pWidget->GetPDFAnnot()->GetRect();
  switch (m_pWidget->GetRotate()) {
    case 90:
      mt = CFX_Matrix(0, 1, -1, 0, rcDA.right - rcDA.left, 0);
      break;
    case 180:
      mt = CFX_Matrix(-1, 0, 0, -1, rcDA.right - rcDA.left,
                      rcDA.top - rcDA.bottom);
      break;
    case 270:
      mt = CFX_Matrix(0, -1, 1, 0, 0, rcDA.top - rcDA.bottom);
      break;
    case 0:
    default:
      break;
  }
  mt.e += rcDA.left;
  mt.f += rcDA.bottom;

  return mt;
}

CFX_FloatRect CFFL_FormField::GetPDFAnnotRect() const {
  CFX_FloatRect rectAnnot = m_pWidget->GetPDFAnnot()->GetRect();

  float fWidth = rectAnnot.Width();
  float fHeight = rectAnnot.Height();
  if ((m_pWidget->GetRotate() / 90) & 0x01)
    std::swap(fWidth, fHeight);
  return CFX_FloatRect(0, 0, fWidth, fHeight);
}

CPDFSDK_PageView* CFFL_FormField::GetCurPageView() {
  IPDF_Page* pPage = m_pWidget->GetPage();
  return m_pFormFillEnv->GetPageView(pPage, true);
}

CFX_FloatRect CFFL_FormField::GetFocusBox(CPDFSDK_PageView* pPageView) {
  CPWL_Wnd* pWnd = GetPWLWindow(pPageView, false);
  if (!pWnd)
    return CFX_FloatRect();

  CFX_FloatRect rcFocus = PWLtoFFL(pWnd->GetFocusRect());
  return pPageView->GetPDFPage()->GetBBox().Contains(rcFocus) ? rcFocus
                                                              : CFX_FloatRect();
}

CFX_FloatRect CFFL_FormField::FFLtoPWL(const CFX_FloatRect& rect) {
  return GetCurMatrix().GetInverse().TransformRect(rect);
}

CFX_FloatRect CFFL_FormField::PWLtoFFL(const CFX_FloatRect& rect) {
  return GetCurMatrix().TransformRect(rect);
}

CFX_PointF CFFL_FormField::FFLtoPWL(const CFX_PointF& point) {
  return GetCurMatrix().GetInverse().Transform(point);
}

CFX_PointF CFFL_FormField::PWLtoFFL(const CFX_PointF& point) {
  return GetCurMatrix().Transform(point);
}

bool CFFL_FormField::CommitData(CPDFSDK_PageView* pPageView, uint32_t nFlag) {
  if (!IsDataChanged(pPageView))
    return true;

  CFFL_InteractiveFormFiller* pInteractiveFormFiller =
      m_pFormFillEnv->GetInteractiveFormFiller();
  ObservedPtr<CPDFSDK_Annot> pObserved(m_pWidget.Get());

  if (!pInteractiveFormFiller->OnKeyStrokeCommit(&pObserved, pPageView,
                                                 nFlag)) {
    if (!pObserved)
      return false;
    ResetPWLWindow(pPageView, false);
    return true;
  }
  if (!pObserved)
    return false;

  if (!pInteractiveFormFiller->OnValidate(&pObserved, pPageView, nFlag)) {
    if (!pObserved)
      return false;
    ResetPWLWindow(pPageView, false);
    return true;
  }
  if (!pObserved)
    return false;

  SaveData(pPageView);  // may invoking JS to delete this widget.
  if (!pObserved)
    return false;

  pInteractiveFormFiller->OnCalculate(&pObserved, pPageView, nFlag);
  if (!pObserved)
    return false;

  pInteractiveFormFiller->OnFormat(&pObserved, pPageView, nFlag);
  if (!pObserved)
    return false;

  return true;
}

bool CFFL_FormField::IsDataChanged(CPDFSDK_PageView* pPageView) {
  return false;
}

void CFFL_FormField::SaveData(CPDFSDK_PageView* pPageView) {}

#ifdef PDF_ENABLE_XFA
bool CFFL_FormField::IsFieldFull(CPDFSDK_PageView* pPageView) {
  return false;
}
#endif  // PDF_ENABLE_XFA

void CFFL_FormField::SetChangeMark() {
  m_pFormFillEnv->OnChange();
}

void CFFL_FormField::GetActionData(CPDFSDK_PageView* pPageView,
                                   CPDF_AAction::AActionType type,
                                   CPDFSDK_FieldAction& fa) {
  fa.sValue = m_pWidget->GetValue();
}

void CFFL_FormField::SetActionData(CPDFSDK_PageView* pPageView,
                                   CPDF_AAction::AActionType type,
                                   const CPDFSDK_FieldAction& fa) {}

void CFFL_FormField::SaveState(CPDFSDK_PageView* pPageView) {}

void CFFL_FormField::RestoreState(CPDFSDK_PageView* pPageView) {}

CPWL_Wnd* CFFL_FormField::ResetPWLWindow(CPDFSDK_PageView* pPageView,
                                         bool bRestoreValue) {
  return GetPWLWindow(pPageView, false);
}

void CFFL_FormField::OnTimerFired() {}

void CFFL_FormField::EscapeFiller(CPDFSDK_PageView* pPageView,
                                  bool bDestroyPWLWindow) {
  m_bValid = false;

  InvalidateRect(GetViewBBox(pPageView));
  if (bDestroyPWLWindow)
    DestroyPWLWindow(pPageView);
}

void CFFL_FormField::InvalidateRect(const FX_RECT& rect) {
  m_pFormFillEnv->Invalidate(m_pWidget->GetPage(), rect);
}
