// 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(cppgc::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);
    }

    view_layout_processor_->SubmitContentItem(pLayoutItem, eStatus);
  } 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_;
}
