// 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 "xfa/fxfa/layout/cxfa_layoutprocessor.h"

#include "fxjs/gc/container_trace.h"
#include "fxjs/xfa/cjx_object.h"
#include "v8/include/cppgc/heap.h"
#include "xfa/fxfa/layout/cxfa_contentlayoutitem.h"
#include "xfa/fxfa/layout/cxfa_contentlayoutprocessor.h"
#include "xfa/fxfa/layout/cxfa_viewlayoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_localemgr.h"
#include "xfa/fxfa/parser/cxfa_measurement.h"
#include "xfa/fxfa/parser/cxfa_node.h"
#include "xfa/fxfa/parser/cxfa_subform.h"
#include "xfa/fxfa/parser/xfa_document_datamerger_imp.h"
#include "xfa/fxfa/parser/xfa_utils.h"

// static
CXFA_LayoutProcessor* CXFA_LayoutProcessor::FromDocument(
    const CXFA_Document* pXFADoc) {
  return static_cast<CXFA_LayoutProcessor*>(pXFADoc->GetLayoutProcessor());
}

CXFA_LayoutProcessor::CXFA_LayoutProcessor(FXGC_Heap* pHeap) : heap_(pHeap) {}

CXFA_LayoutProcessor::~CXFA_LayoutProcessor() = default;

void CXFA_LayoutProcessor::Trace(cppgc::Visitor* visitor) const {
  CXFA_Document::LayoutProcessorIface::Trace(visitor);
  visitor->Trace(view_layout_processor_);
  visitor->Trace(content_layout_processor_);
}

void CXFA_LayoutProcessor::SetForceRelayout() {
  need_layout_ = true;
}

int32_t CXFA_LayoutProcessor::StartLayout() {
  return NeedLayout() ? RestartLayout() : 100;
}

int32_t CXFA_LayoutProcessor::RestartLayout() {
  content_layout_processor_ = nullptr;
  progress_counter_ = 0;
  CXFA_Node* pFormPacketNode =
      ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form));
  if (!pFormPacketNode) {
    return -1;
  }

  CXFA_Subform* pFormRoot =
      pFormPacketNode->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
  if (!pFormRoot) {
    return -1;
  }

  if (!view_layout_processor_) {
    view_layout_processor_ =
        cppgc::MakeGarbageCollected<CXFA_ViewLayoutProcessor>(
            GetHeap()->GetAllocationHandle(), GetHeap(), this);
  }
  if (!view_layout_processor_->InitLayoutPage(pFormRoot)) {
    return -1;
  }

  if (!view_layout_processor_->PrepareFirstPage(pFormRoot)) {
    return -1;
  }

  content_layout_processor_ =
      cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
          GetHeap()->GetAllocationHandle(), GetHeap(), pFormRoot,
          view_layout_processor_);
  progress_counter_ = 1;
  return 0;
}

int32_t CXFA_LayoutProcessor::DoLayout() {
  if (progress_counter_ < 1) {
    return -1;
  }

  CXFA_ContentLayoutProcessor::Result eStatus;
  CXFA_Node* pFormNode = content_layout_processor_->GetFormNode();
  float fPosX =
      pFormNode->JSObject()->GetMeasureInUnit(XFA_Attribute::X, XFA_Unit::Pt);
  float fPosY =
      pFormNode->JSObject()->GetMeasureInUnit(XFA_Attribute::Y, XFA_Unit::Pt);
  do {
    float fAvailHeight = view_layout_processor_->GetAvailHeight();
    eStatus =
        content_layout_processor_->DoLayout(true, fAvailHeight, fAvailHeight);
    if (eStatus != CXFA_ContentLayoutProcessor::Result::kDone) {
      progress_counter_++;
    }

    CXFA_ContentLayoutItem* pLayoutItem =
        content_layout_processor_->ExtractLayoutItem();
    if (pLayoutItem) {
      pLayoutItem->s_pos_ = CFX_PointF(fPosX, fPosY);
    }

    if (!view_layout_processor_->SubmitContentItem(pLayoutItem, eStatus)) {
      return -1;
    }
  } while (eStatus != CXFA_ContentLayoutProcessor::Result::kDone);

  if (eStatus == CXFA_ContentLayoutProcessor::Result::kDone) {
    view_layout_processor_->FinishPaginatedPageSets();
    view_layout_processor_->SyncLayoutData();
    has_changed_containers_ = false;
    need_layout_ = false;
  }
  return 100 *
         (eStatus == CXFA_ContentLayoutProcessor::Result::kDone
              ? progress_counter_
              : progress_counter_ - 1) /
         progress_counter_;
}

bool CXFA_LayoutProcessor::IncrementLayout() {
  if (need_layout_) {
    RestartLayout();
    return DoLayout() == 100;
  }
  return !has_changed_containers_;
}

int32_t CXFA_LayoutProcessor::CountPages() const {
  return view_layout_processor_ ? view_layout_processor_->GetPageCount() : 0;
}

CXFA_ViewLayoutItem* CXFA_LayoutProcessor::GetPage(int32_t index) const {
  return view_layout_processor_ ? view_layout_processor_->GetPage(index)
                                : nullptr;
}

CXFA_LayoutItem* CXFA_LayoutProcessor::GetLayoutItem(CXFA_Node* pFormItem) {
  return pFormItem->JSObject()->GetLayoutItem();
}

void CXFA_LayoutProcessor::SetHasChangedContainer() {
  has_changed_containers_ = true;
}

bool CXFA_LayoutProcessor::NeedLayout() const {
  return need_layout_ || has_changed_containers_;
}
