// 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 "xfa/src/foxitlib.h"
#include "xfa/src/fxfa/src/common/xfa_utils.h"
#include "xfa/src/fxfa/src/common/xfa_object.h"
#include "xfa/src/fxfa/src/common/xfa_document.h"
#include "xfa/src/fxfa/src/common/xfa_parser.h"
#include "xfa/src/fxfa/src/common/xfa_script.h"
#include "xfa/src/fxfa/src/common/xfa_docdata.h"
#include "xfa/src/fxfa/src/common/xfa_doclayout.h"
#include "xfa/src/fxfa/src/common/xfa_localemgr.h"
#include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h"
#include "xfa_basic_imp.h"
#include "xfa_document_layout_imp.h"
#include "xfa_document_datamerger_imp.h"
#include "xfa_layout_itemlayout.h"
#include "xfa_layout_pagemgr_new.h"
#include "xfa_layout_appadapter.h"
CXFA_LayoutProcessor* CXFA_Document::GetLayoutProcessor() {
  if (!m_pLayoutProcessor) {
    m_pLayoutProcessor = new CXFA_LayoutProcessor(this);
    ASSERT(m_pLayoutProcessor);
  }
  return m_pLayoutProcessor;
}
IXFA_DocLayout* CXFA_Document::GetDocLayout() {
  return GetLayoutProcessor();
}
CXFA_LayoutProcessor::CXFA_LayoutProcessor(CXFA_Document* pDocument)
    : m_pDocument(pDocument),
      m_pRootItemLayoutProcessor(NULL),
      m_pLayoutPageMgr(NULL),
      m_nProgressCounter(0),
      m_bNeeLayout(TRUE) {}
CXFA_LayoutProcessor::~CXFA_LayoutProcessor() {
  ClearLayoutData();
}
CXFA_Document* CXFA_LayoutProcessor::GetDocument() const {
  return m_pDocument;
}
int32_t CXFA_LayoutProcessor::StartLayout(FX_BOOL bForceRestart) {
  if (!bForceRestart && !IsNeedLayout()) {
    return 100;
  }
  if (m_pRootItemLayoutProcessor) {
    delete m_pRootItemLayoutProcessor;
    m_pRootItemLayoutProcessor = NULL;
  }
  m_nProgressCounter = 0;
  CXFA_Node* pFormPacketNode =
      ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Form));
  if (!pFormPacketNode) {
    return -1;
  }
  CXFA_Node* pFormRoot =
      pFormPacketNode->GetFirstChildByClass(XFA_ELEMENT_Subform);
  if (!pFormRoot) {
    return -1;
  }
  if (!m_pLayoutPageMgr) {
    m_pLayoutPageMgr = new CXFA_LayoutPageMgr(this);
  }
  if (!m_pLayoutPageMgr->InitLayoutPage(pFormRoot)) {
    return -1;
  }
  if (!m_pLayoutPageMgr->PrepareFirstPage(pFormRoot)) {
    return -1;
  }
  m_pRootItemLayoutProcessor =
      new CXFA_ItemLayoutProcessor(pFormRoot, m_pLayoutPageMgr);
#ifndef _XFA_LAYOUTITEM_ProcessCACHE_
  m_pRootItemLayoutProcessor->m_pPageMgrCreateItem = m_pLayoutPageMgr;
#endif
  m_nProgressCounter = 1;
  return 0;
}
int32_t CXFA_LayoutProcessor::DoLayout(IFX_Pause* pPause) {
  if (m_nProgressCounter < 1) {
    return -1;
  }
  XFA_ItemLayoutProcessorResult eStatus;
  CXFA_Node* pFormNode = m_pRootItemLayoutProcessor->GetFormNode();
  FX_FLOAT fPosX = pFormNode->GetMeasure(XFA_ATTRIBUTE_X).ToUnit(XFA_UNIT_Pt);
  FX_FLOAT fPosY = pFormNode->GetMeasure(XFA_ATTRIBUTE_Y).ToUnit(XFA_UNIT_Pt);
  do {
    FX_FLOAT fAvailHeight = m_pLayoutPageMgr->GetAvailHeight();
    eStatus =
        m_pRootItemLayoutProcessor->DoLayout(TRUE, fAvailHeight, fAvailHeight);
    if (eStatus != XFA_ItemLayoutProcessorResult_Done) {
      m_nProgressCounter++;
    }
    CXFA_ContentLayoutItem* pLayoutItem =
        m_pRootItemLayoutProcessor->ExtractLayoutItem();
    if (pLayoutItem) {
      pLayoutItem->m_sPos.Set(fPosX, fPosY);
    }
    m_pLayoutPageMgr->SubmitContentItem(pLayoutItem, eStatus);
  } while (eStatus != XFA_ItemLayoutProcessorResult_Done &&
           (!pPause || !pPause->NeedToPauseNow()));
  if (eStatus == XFA_ItemLayoutProcessorResult_Done) {
    m_pLayoutPageMgr->FinishPaginatedPageSets();
    m_pLayoutPageMgr->SyncLayoutData();
    m_bNeeLayout = FALSE;
    m_rgChangedContainers.RemoveAll();
  }
  return 100 * (eStatus == XFA_ItemLayoutProcessorResult_Done
                    ? m_nProgressCounter
                    : m_nProgressCounter - 1) /
         m_nProgressCounter;
}
FX_BOOL CXFA_LayoutProcessor::IncrementLayout() {
  if (m_bNeeLayout) {
    StartLayout(TRUE);
    return DoLayout(NULL) == 100;
  }
  for (int32_t i = 0, c = m_rgChangedContainers.GetSize(); i < c; i++) {
    CXFA_Node* pNode = m_rgChangedContainers[i];
    CXFA_Node* pParentNode =
        pNode->GetNodeItem(XFA_NODEITEM_Parent, XFA_OBJECTTYPE_ContainerNode);
    if (!pParentNode) {
      return FALSE;
    }
    if (!CXFA_ItemLayoutProcessor::IncrementRelayoutNode(this, pNode,
                                                         pParentNode)) {
      return FALSE;
    }
  }
  m_rgChangedContainers.RemoveAll();
  return TRUE;
}
int32_t CXFA_LayoutProcessor::CountPages() const {
  return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetPageCount() : 0;
}
IXFA_LayoutPage* CXFA_LayoutProcessor::GetPage(int32_t index) const {
  return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetPage(index) : NULL;
}
CXFA_LayoutItem* CXFA_LayoutProcessor::GetLayoutItem(CXFA_Node* pFormItem) {
  return static_cast<CXFA_LayoutItem*>(
      pFormItem->GetUserData(XFA_LAYOUTITEMKEY));
}
void CXFA_LayoutProcessor::AddChangedContainer(CXFA_Node* pContainer) {
  if (m_rgChangedContainers.Find(pContainer) < 0) {
    m_rgChangedContainers.Add(pContainer);
  }
}
CXFA_ContainerLayoutItem* CXFA_LayoutProcessor::GetRootLayoutItem() const {
  return m_pLayoutPageMgr ? m_pLayoutPageMgr->GetRootLayoutItem() : NULL;
}
void CXFA_LayoutProcessor::ClearLayoutData() {
  if (m_pLayoutPageMgr) {
    delete m_pLayoutPageMgr;
    m_pLayoutPageMgr = NULL;
  }
  if (m_pRootItemLayoutProcessor) {
    delete m_pRootItemLayoutProcessor;
    m_pRootItemLayoutProcessor = NULL;
  }
  m_nProgressCounter = 0;
}
FX_BOOL CXFA_LayoutProcessor::IsNeedLayout() {
  return m_bNeeLayout || m_rgChangedContainers.GetSize() > 0;
}
CXFA_LayoutItem::CXFA_LayoutItem(CXFA_Node* pNode, FX_BOOL bIsContentLayoutItem)
    : m_pFormNode(pNode),
      m_pParent(NULL),
      m_pNextSibling(NULL),
      m_pFirstChild(NULL),
      m_bIsContentLayoutItem(bIsContentLayoutItem) {
}
CXFA_LayoutItem::~CXFA_LayoutItem() {
}
CXFA_ContainerLayoutItem::CXFA_ContainerLayoutItem(CXFA_Node* pNode)
    : CXFA_LayoutItem(pNode, FALSE), m_pOldSubform(NULL) {
}
IXFA_DocLayout* CXFA_ContainerLayoutItem::GetLayout() const {
  return m_pFormNode->GetDocument()->GetLayoutProcessor();
}
int32_t CXFA_ContainerLayoutItem::GetPageIndex() const {
  return m_pFormNode->GetDocument()
      ->GetLayoutProcessor()
      ->GetLayoutPageMgr()
      ->GetPageIndex(this);
}
void CXFA_ContainerLayoutItem::GetPageSize(CFX_SizeF& size) {
  size.Set(0, 0);
  CXFA_Node* pMedium = m_pFormNode->GetFirstChildByClass(XFA_ELEMENT_Medium);
  if (pMedium) {
    size.x = pMedium->GetMeasure(XFA_ATTRIBUTE_Short).ToUnit(XFA_UNIT_Pt);
    size.y = pMedium->GetMeasure(XFA_ATTRIBUTE_Long).ToUnit(XFA_UNIT_Pt);
    if (pMedium->GetEnum(XFA_ATTRIBUTE_Orientation) ==
        XFA_ATTRIBUTEENUM_Landscape) {
      size.Set(size.y, size.x);
    }
  }
}
CXFA_Node* CXFA_ContainerLayoutItem::GetMasterPage() const {
  return m_pFormNode;
}
CXFA_ContentLayoutItem::CXFA_ContentLayoutItem(CXFA_Node* pNode)
    : CXFA_LayoutItem(pNode, TRUE),
      m_pPrev(NULL),
      m_pNext(NULL),
      m_dwStatus(0) {
}
CXFA_ContentLayoutItem::~CXFA_ContentLayoutItem() {
  if (m_pFormNode->GetUserData(XFA_LAYOUTITEMKEY) == this) {
    m_pFormNode->SetUserData(XFA_LAYOUTITEMKEY, NULL);
  }
}
