// Copyright 2016 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/cpdfsdk_baannot.h"

#include <vector>

#include "constants/annotation_common.h"
#include "constants/annotation_flags.h"
#include "constants/form_fields.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxge/cfx_drawutils.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "third_party/base/check.h"
#include "third_party/base/containers/contains.h"

CPDFSDK_BAAnnot::CPDFSDK_BAAnnot(CPDF_Annot* pAnnot,
                                 CPDFSDK_PageView* pPageView)
    : CPDFSDK_Annot(pPageView), m_pAnnot(pAnnot) {}

CPDFSDK_BAAnnot::~CPDFSDK_BAAnnot() = default;

CPDFSDK_BAAnnot* CPDFSDK_BAAnnot::AsBAAnnot() {
  return this;
}

CPDFSDK_Annot::UnsafeInputHandlers* CPDFSDK_BAAnnot::GetUnsafeInputHandlers() {
  return this;
}

CPDF_Annot* CPDFSDK_BAAnnot::GetPDFAnnot() const {
  return m_pAnnot.Get();
}

CPDF_Annot* CPDFSDK_BAAnnot::GetPDFPopupAnnot() const {
  return m_pAnnot->GetPopupAnnot();
}

const CPDF_Dictionary* CPDFSDK_BAAnnot::GetAnnotDict() const {
  return m_pAnnot->GetAnnotDict();
}

RetainPtr<CPDF_Dictionary> CPDFSDK_BAAnnot::GetMutableAnnotDict() {
  return m_pAnnot->GetMutableAnnotDict();
}

RetainPtr<CPDF_Dictionary> CPDFSDK_BAAnnot::GetAPDict() {
  return GetMutableAnnotDict()->GetOrCreateDictFor(pdfium::annotation::kAP);
}

void CPDFSDK_BAAnnot::ClearCachedAnnotAP() {
  m_pAnnot->ClearCachedAP();
}

bool CPDFSDK_BAAnnot::IsFocusableAnnot(
    const CPDF_Annot::Subtype& annot_type) const {
  return pdfium::Contains(
      GetPageView()->GetFormFillEnv()->GetFocusableAnnotSubtypes(), annot_type);
}

CFX_FloatRect CPDFSDK_BAAnnot::GetRect() const {
  return m_pAnnot->GetRect();
}

CPDF_Annot::Subtype CPDFSDK_BAAnnot::GetAnnotSubtype() const {
  return m_pAnnot->GetSubtype();
}

void CPDFSDK_BAAnnot::DrawAppearance(CFX_RenderDevice* pDevice,
                                     const CFX_Matrix& mtUser2Device,
                                     CPDF_Annot::AppearanceMode mode) {
  m_pAnnot->DrawAppearance(GetPageView()->GetPDFPage(), pDevice, mtUser2Device,
                           mode);
}

bool CPDFSDK_BAAnnot::IsAppearanceValid() {
  return !!GetAnnotDict()->GetDictFor(pdfium::annotation::kAP);
}

void CPDFSDK_BAAnnot::SetAnnotName(const WideString& sName) {
  RetainPtr<CPDF_Dictionary> pDict = GetMutableAnnotDict();
  if (sName.IsEmpty()) {
    pDict->RemoveFor(pdfium::annotation::kNM);
    return;
  }
  pDict->SetNewFor<CPDF_String>(pdfium::annotation::kNM, sName.AsStringView());
}

WideString CPDFSDK_BAAnnot::GetAnnotName() const {
  return GetAnnotDict()->GetUnicodeTextFor(pdfium::annotation::kNM);
}

void CPDFSDK_BAAnnot::SetFlags(uint32_t nFlags) {
  GetMutableAnnotDict()->SetNewFor<CPDF_Number>(pdfium::annotation::kF,
                                                static_cast<int>(nFlags));
}

uint32_t CPDFSDK_BAAnnot::GetFlags() const {
  return GetAnnotDict()->GetIntegerFor(pdfium::annotation::kF);
}

void CPDFSDK_BAAnnot::SetAppStateOff() {
  RetainPtr<CPDF_Dictionary> pDict = GetMutableAnnotDict();
  pDict->SetNewFor<CPDF_String>(pdfium::annotation::kAS, "Off", false);
}

ByteString CPDFSDK_BAAnnot::GetAppState() const {
  return GetAnnotDict()->GetStringFor(pdfium::annotation::kAS);
}

void CPDFSDK_BAAnnot::SetBorderWidth(int nWidth) {
  RetainPtr<CPDF_Dictionary> pAnnotDict = GetMutableAnnotDict();
  RetainPtr<CPDF_Array> pBorder =
      pAnnotDict->GetMutableArrayFor(pdfium::annotation::kBorder);
  if (pBorder) {
    pBorder->SetNewAt<CPDF_Number>(2, nWidth);
    return;
  }
  pAnnotDict->GetOrCreateDictFor("BS")->SetNewFor<CPDF_Number>("W", nWidth);
}

int CPDFSDK_BAAnnot::GetBorderWidth() const {
  const CPDF_Array* pBorder =
      GetAnnotDict()->GetArrayFor(pdfium::annotation::kBorder);
  if (pBorder)
    return pBorder->GetIntegerAt(2);

  const CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS");
  if (pBSDict)
    return pBSDict->GetIntegerFor("W", 1);

  return 1;
}

void CPDFSDK_BAAnnot::SetBorderStyle(BorderStyle nStyle) {
  RetainPtr<CPDF_Dictionary> pBSDict =
      GetMutableAnnotDict()->GetOrCreateDictFor("BS");
  const char* name = nullptr;
  switch (nStyle) {
    case BorderStyle::kSolid:
      name = "S";
      break;
    case BorderStyle::kDash:
      name = "D";
      break;
    case BorderStyle::kBeveled:
      name = "B";
      break;
    case BorderStyle::kInset:
      name = "I";
      break;
    case BorderStyle::kUnderline:
      name = "U";
      break;
    default:
      return;
  }
  pBSDict->SetNewFor<CPDF_Name>("S", name);
}

BorderStyle CPDFSDK_BAAnnot::GetBorderStyle() const {
  const CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS");
  if (pBSDict) {
    ByteString sBorderStyle = pBSDict->GetStringFor("S", "S");
    if (sBorderStyle == "S")
      return BorderStyle::kSolid;
    if (sBorderStyle == "D")
      return BorderStyle::kDash;
    if (sBorderStyle == "B")
      return BorderStyle::kBeveled;
    if (sBorderStyle == "I")
      return BorderStyle::kInset;
    if (sBorderStyle == "U")
      return BorderStyle::kUnderline;
  }

  const CPDF_Array* pBorder =
      GetAnnotDict()->GetArrayFor(pdfium::annotation::kBorder);
  if (pBorder) {
    if (pBorder->size() >= 4) {
      const CPDF_Array* pDP = pBorder->GetArrayAt(3);
      if (pDP && pDP->size() > 0)
        return BorderStyle::kDash;
    }
  }

  return BorderStyle::kSolid;
}

bool CPDFSDK_BAAnnot::IsVisible() const {
  uint32_t nFlags = GetFlags();
  return !((nFlags & pdfium::annotation_flags::kInvisible) ||
           (nFlags & pdfium::annotation_flags::kHidden) ||
           (nFlags & pdfium::annotation_flags::kNoView));
}

CPDF_Action CPDFSDK_BAAnnot::GetAction() const {
  return CPDF_Action(GetAnnotDict()->GetDictFor("A"));
}

CPDF_AAction CPDFSDK_BAAnnot::GetAAction() const {
  return CPDF_AAction(GetAnnotDict()->GetDictFor(pdfium::form_fields::kAA));
}

CPDF_Action CPDFSDK_BAAnnot::GetAAction(CPDF_AAction::AActionType eAAT) {
  CPDF_AAction AAction = GetAAction();
  if (AAction.ActionExist(eAAT))
    return AAction.GetAction(eAAT);

  if (eAAT == CPDF_AAction::kButtonUp || eAAT == CPDF_AAction::kKeyStroke)
    return GetAction();

  return CPDF_Action(nullptr);
}

void CPDFSDK_BAAnnot::SetOpenState(bool bOpenState) {
  if (CPDF_Annot* pAnnot = m_pAnnot->GetPopupAnnot())
    pAnnot->SetOpenState(bOpenState);
}

void CPDFSDK_BAAnnot::UpdateAnnotRects() {
  std::vector<CFX_FloatRect> rects;
  rects.push_back(GetRect());
  CPDF_Annot* popup = GetPDFPopupAnnot();
  if (popup)
    rects.push_back(popup->GetRect());

  // Make the rects round up to avoid https://crbug.com/662804
  for (CFX_FloatRect& rect : rects)
    rect.Inflate(1, 1);

  GetPageView()->UpdateRects(rects);
}

void CPDFSDK_BAAnnot::InvalidateRect() {
  CFX_FloatRect view_bounding_box = GetViewBBox();
  if (view_bounding_box.IsEmpty())
    return;

  view_bounding_box.Inflate(1, 1);
  view_bounding_box.Normalize();
  FX_RECT rect = view_bounding_box.GetOuterRect();
  GetPageView()->GetFormFillEnv()->Invalidate(GetPage(), rect);
}

int CPDFSDK_BAAnnot::GetLayoutOrder() const {
  if (m_pAnnot->GetSubtype() == CPDF_Annot::Subtype::POPUP)
    return 1;

  return CPDFSDK_Annot::GetLayoutOrder();
}

void CPDFSDK_BAAnnot::OnDraw(CFX_RenderDevice* pDevice,
                             const CFX_Matrix& mtUser2Device,
                             bool bDrawAnnots) {
  if (!IsVisible())
    return;

  const CPDF_Annot::Subtype annot_type = GetAnnotSubtype();
  if (bDrawAnnots && annot_type == CPDF_Annot::Subtype::POPUP) {
    DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::AppearanceMode::kNormal);
    return;
  }

  if (!is_focused_ || !IsFocusableAnnot(annot_type) ||
      this != GetPageView()->GetFormFillEnv()->GetFocusAnnot()) {
    return;
  }

  CFX_FloatRect view_bounding_box = GetViewBBox();
  if (view_bounding_box.IsEmpty())
    return;

  view_bounding_box.Normalize();
  CFX_DrawUtils::DrawFocusRect(pDevice, mtUser2Device, view_bounding_box);
}

bool CPDFSDK_BAAnnot::DoHitTest(const CFX_PointF& point) {
  return false;
}

CFX_FloatRect CPDFSDK_BAAnnot::GetViewBBox() {
  return GetRect();
}

void CPDFSDK_BAAnnot::OnMouseEnter(Mask<FWL_EVENTFLAG> nFlags) {
  SetOpenState(true);
  UpdateAnnotRects();
}

void CPDFSDK_BAAnnot::OnMouseExit(Mask<FWL_EVENTFLAG> nFlags) {
  SetOpenState(false);
  UpdateAnnotRects();
}

bool CPDFSDK_BAAnnot::OnLButtonDown(Mask<FWL_EVENTFLAG> nFlags,
                                    const CFX_PointF& point) {
  return false;
}

bool CPDFSDK_BAAnnot::OnLButtonUp(Mask<FWL_EVENTFLAG> nFlags,
                                  const CFX_PointF& point) {
  return false;
}

bool CPDFSDK_BAAnnot::OnLButtonDblClk(Mask<FWL_EVENTFLAG> nFlags,
                                      const CFX_PointF& point) {
  return false;
}

bool CPDFSDK_BAAnnot::OnMouseMove(Mask<FWL_EVENTFLAG> nFlags,
                                  const CFX_PointF& point) {
  return false;
}

bool CPDFSDK_BAAnnot::OnMouseWheel(Mask<FWL_EVENTFLAG> nFlags,
                                   const CFX_PointF& point,
                                   const CFX_Vector& delta) {
  return false;
}

bool CPDFSDK_BAAnnot::OnRButtonDown(Mask<FWL_EVENTFLAG> nFlags,
                                    const CFX_PointF& point) {
  return false;
}

bool CPDFSDK_BAAnnot::OnRButtonUp(Mask<FWL_EVENTFLAG> nFlags,
                                  const CFX_PointF& point) {
  return false;
}

bool CPDFSDK_BAAnnot::OnChar(uint32_t nChar, Mask<FWL_EVENTFLAG> nFlags) {
  return false;
}

bool CPDFSDK_BAAnnot::OnKeyDown(FWL_VKEYCODE nKeyCode,
                                Mask<FWL_EVENTFLAG> nFlags) {
  // OnKeyDown() is implemented only for link annotations for now. As
  // OnKeyDown() is implemented for other subtypes, following check should be
  // modified.
  if (nKeyCode != FWL_VKEY_Return ||
      GetAnnotSubtype() != CPDF_Annot::Subtype::LINK) {
    return false;
  }

  CPDF_Action action = GetAAction(CPDF_AAction::kKeyStroke);
  CPDFSDK_FormFillEnvironment* env = GetPageView()->GetFormFillEnv();
  if (action.GetDict()) {
    return env->DoActionLink(action, CPDF_AAction::kKeyStroke, nFlags);
  }

  return env->DoActionDestination(GetDestination());
}

bool CPDFSDK_BAAnnot::OnSetFocus(Mask<FWL_EVENTFLAG> nFlags) {
  if (!IsFocusableAnnot(GetAnnotSubtype()))
    return false;

  is_focused_ = true;
  InvalidateRect();
  return true;
}

bool CPDFSDK_BAAnnot::OnKillFocus(Mask<FWL_EVENTFLAG> nFlags) {
  if (!IsFocusableAnnot(GetAnnotSubtype()))
    return false;

  is_focused_ = false;
  InvalidateRect();
  return true;
}

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

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

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

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

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

WideString CPDFSDK_BAAnnot::GetSelectedText() {
  return WideString();
}

void CPDFSDK_BAAnnot::ReplaceSelection(const WideString& text) {}

bool CPDFSDK_BAAnnot::SelectAllText() {
  return false;
}

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

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

CPDF_Dest CPDFSDK_BAAnnot::GetDestination() const {
  if (m_pAnnot->GetSubtype() != CPDF_Annot::Subtype::LINK)
    return CPDF_Dest(nullptr);

  // Link annotations can have "Dest" entry defined as an explicit array.
  // See ISO 32000-1:2008 spec, section 12.3.2.1.
  return CPDF_Dest::Create(GetPageView()->GetPDFDocument(),
                           GetAnnotDict()->GetDirectObjectFor("Dest"));
}
