// Copyright 2016 The PDFium Authors
// 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 "core/fpdfapi/page/cpdf_form.h"

#include <algorithm>
#include <memory>

#include "core/fpdfapi/page/cpdf_contentparser.h"
#include "core/fpdfapi/page/cpdf_imageobject.h"
#include "core/fpdfapi/page/cpdf_pageobject.h"
#include "core/fpdfapi/page/cpdf_pageobjectholder.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "third_party/base/check_op.h"

// static
CPDF_Dictionary* CPDF_Form::ChooseResourcesDict(
    CPDF_Dictionary* pResources,
    CPDF_Dictionary* pParentResources,
    CPDF_Dictionary* pPageResources) {
  if (pResources)
    return pResources;
  return pParentResources ? pParentResources : pPageResources;
}

CPDF_Form::CPDF_Form(CPDF_Document* pDoc,
                     RetainPtr<CPDF_Dictionary> pPageResources,
                     RetainPtr<CPDF_Stream> pFormStream)
    : CPDF_Form(pDoc,
                std::move(pPageResources),
                std::move(pFormStream),
                nullptr) {}

CPDF_Form::CPDF_Form(CPDF_Document* pDoc,
                     RetainPtr<CPDF_Dictionary> pPageResources,
                     RetainPtr<CPDF_Stream> pFormStream,
                     CPDF_Dictionary* pParentResources)
    : CPDF_PageObjectHolder(pDoc,
                            pFormStream->GetMutableDict(),
                            pPageResources,
                            pdfium::WrapRetain(ChooseResourcesDict(
                                pFormStream->GetMutableDict()
                                    ->GetMutableDictFor("Resources")
                                    .Get(),
                                pParentResources,
                                pPageResources.Get()))),
      m_pFormStream(std::move(pFormStream)) {
  LoadTransparencyInfo();
}

CPDF_Form::~CPDF_Form() = default;

void CPDF_Form::ParseContent() {
  ParseContentInternal(nullptr, nullptr, nullptr, nullptr);
}

void CPDF_Form::ParseContent(const CPDF_AllStates* pGraphicStates,
                             const CFX_Matrix* pParentMatrix,
                             std::set<const uint8_t*>* pParsedSet) {
  ParseContentInternal(pGraphicStates, pParentMatrix, nullptr, pParsedSet);
}

void CPDF_Form::ParseContentForType3Char(CPDF_Type3Char* pType3Char) {
  ParseContentInternal(nullptr, nullptr, pType3Char, nullptr);
}

void CPDF_Form::ParseContentInternal(const CPDF_AllStates* pGraphicStates,
                                     const CFX_Matrix* pParentMatrix,
                                     CPDF_Type3Char* pType3Char,
                                     std::set<const uint8_t*>* pParsedSet) {
  if (GetParseState() == ParseState::kParsed)
    return;

  if (GetParseState() == ParseState::kNotParsed) {
    StartParse(std::make_unique<CPDF_ContentParser>(
        GetStream(), this, pGraphicStates, pParentMatrix, pType3Char,
        pParsedSet ? pParsedSet : &m_ParsedSet));
  }
  DCHECK_EQ(GetParseState(), ParseState::kParsing);
  ContinueParse(nullptr);
}

bool CPDF_Form::HasPageObjects() const {
  return GetPageObjectCount() != 0;
}

CFX_FloatRect CPDF_Form::CalcBoundingBox() const {
  if (GetPageObjectCount() == 0)
    return CFX_FloatRect();

  float left = 1000000.0f;
  float right = -1000000.0f;
  float bottom = 1000000.0f;
  float top = -1000000.0f;
  for (const auto& pObj : *this) {
    const auto& rect = pObj->GetRect();
    left = std::min(left, rect.left);
    right = std::max(right, rect.right);
    bottom = std::min(bottom, rect.bottom);
    top = std::max(top, rect.top);
  }
  return CFX_FloatRect(left, bottom, right, top);
}

RetainPtr<const CPDF_Stream> CPDF_Form::GetStream() const {
  return m_pFormStream;
}

absl::optional<std::pair<RetainPtr<CFX_DIBitmap>, CFX_Matrix>>
CPDF_Form::GetBitmapAndMatrixFromSoleImageOfForm() const {
  if (GetPageObjectCount() != 1)
    return absl::nullopt;

  CPDF_ImageObject* pImageObject = (*begin())->AsImage();
  if (!pImageObject)
    return absl::nullopt;

  return {{pImageObject->GetIndependentBitmap(), pImageObject->matrix()}};
}
