//========================================================================
//
// StructTreeRoot.cc
//
// This file is licensed under the GPLv2 or later
//
// Copyright 2013, 2014 Igalia S.L.
// Copyright 2014 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright 2017 Jan-Erik S <janerik234678@gmail.com>
// Copyright 2017, 2018 Albert Astals Cid <aacid@kde.org>
// Copyright 2017, 2018 Adrian Johnson <ajohnson@redneon.com>
// Copyright 2018, Adam Reichold <adam.reichold@t-online.de>
//
//========================================================================

#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif

#include "goo/GooString.h"
#include "StructTreeRoot.h"
#include "StructElement.h"
#include "PDFDoc.h"
#include "Object.h"
#include "Dict.h"
#include <set>
#include <assert.h>


StructTreeRoot::StructTreeRoot(PDFDoc *docA, Dict *structTreeRootDict):
  doc(docA)
{
  assert(doc);
  assert(structTreeRootDict);
  parse(structTreeRootDict);
}

StructTreeRoot::~StructTreeRoot()
{
  for (ElemPtrArray::iterator i = elements.begin(); i != elements.end(); ++i)
    delete *i;
}

void StructTreeRoot::parse(Dict *root)
{
  // The RoleMap/ClassMap dictionaries are needed by all the parsing
  // functions, which will resolve the custom names to canonical
  // standard names.
  roleMap = root->lookup("RoleMap");
  classMap = root->lookup("ClassMap");

  // ParentTree (optional). If present, it must be a number tree,
  // otherwise it is not possible to map stream objects to their
  // corresponsing structure element. Here only the references are
  // loaded into the array, the pointers to the StructElements will
  // be filled-in later when parsing them.
  const Object parentTreeObj = root->lookup("ParentTree");
  if (parentTreeObj.isDict()) {
    parseNumberTreeNode(parentTreeObj.getDict());
  }

  std::set<int> seenElements;

  // Parse the children StructElements
  const GBool marked = doc->getCatalog()->getMarkInfo() & Catalog::markInfoMarked;
  Object kids = root->lookup("K");
  if (kids.isArray()) {
    if (marked && kids.arrayGetLength() > 1) {
      error(errSyntaxWarning, -1, "K in StructTreeRoot has more than one children in a tagged PDF");
    }
    for (int i = 0; i < kids.arrayGetLength(); i++) {
      Object ref = kids.arrayGetNF(i);
      if (ref.isRef()) {
        seenElements.insert(ref.getRefNum());
      }
      Object obj = kids.arrayGet(i);
      if (obj.isDict()) {
        StructElement *child = new StructElement(obj.getDict(), this, nullptr, seenElements);
        if (child->isOk()) {
          if (marked && !(child->getType() == StructElement::Document ||
                          child->getType() == StructElement::Part ||
                          child->getType() == StructElement::Art ||
                          child->getType() == StructElement::Div)) {
            error(errSyntaxWarning, -1, "StructTreeRoot element of tagged PDF is wrong type ({0:s})", child->getTypeName());
          }
          appendChild(child);
          if (ref.isRef()) {
            parentTreeAdd(ref.getRef(), child);
          }
        } else {
          error(errSyntaxWarning, -1, "StructTreeRoot element could not be parsed");
          delete child;
        }
      } else {
        error(errSyntaxWarning, -1, "K has a child of wrong type ({0:s})", obj.getTypeName());
      }
    }
  } else if (kids.isDict()) {
    StructElement *child = new StructElement(kids.getDict(), this, nullptr, seenElements);
    if (child->isOk()) {
      appendChild(child);
      Object ref = root->lookupNF("K");
      if (ref.isRef())
        parentTreeAdd(ref.getRef(), child);
    } else {
      error(errSyntaxWarning, -1, "StructTreeRoot element could not be parsed");
      delete child;
    }
  } else if (!kids.isNull()) {
    error(errSyntaxWarning, -1, "K in StructTreeRoot is wrong type ({0:s})", kids.getTypeName());
  }

  // refToParentMap is only used during parsing. Ensure all memory used by it is freed.
  std::multimap<Ref, Parent*>().swap(refToParentMap);
}

void StructTreeRoot::parseNumberTreeNode(Dict *node)
{
  Object kids = node->lookup("Kids");
  if (kids.isArray()) {
    for (int i = 0; i < kids.arrayGetLength(); i++) {
      Object obj = kids.arrayGet(i);
      if (obj.isDict()) {
	parseNumberTreeNode(obj.getDict());
      } else {
	error(errSyntaxError, -1, "Kids item at position {0:d} is wrong type ({1:s})", i, obj.getTypeName());
      }
    }
    return;
  } else if (!kids.isNull()) {
    error(errSyntaxError, -1, "Kids object is wrong type ({0:s})", kids.getTypeName());
  }

  Object nums = node->lookup("Nums");
  if (nums.isArray()) {
    if (nums.arrayGetLength() % 2 == 0) {
      // keys in even positions, references in odd ones
      for (int i = 0; i < nums.arrayGetLength(); i += 2) {
	Object key = nums.arrayGet(i);

	if (!key.isInt()) {
	  error(errSyntaxError, -1, "Nums item at position {0:d} is wrong type ({1:s})", i, key.getTypeName());
	  continue;
	}
	int keyVal = key.getInt();
	std::vector<Parent>& vec = parentTree[keyVal];

	Object value = nums.arrayGet(i + 1);
	if (value.isArray()) {
	  vec.resize(value.arrayGetLength());
	  for (int j = 0; j < value.arrayGetLength(); j++) {
	    Object itemvalue = value.arrayGetNF(j);
	    if (itemvalue.isRef()) {
	      Ref ref = itemvalue.getRef();
	      vec[j].ref = ref;
	      refToParentMap.insert(std::pair<Ref, Parent*>(ref, &vec[j]));
	    } else if (!itemvalue.isNull()) {
	      error(errSyntaxError, -1, "Nums array item at position {0:d}/{1:d} is invalid type ({2:s})", i, j, itemvalue.getTypeName());
	    }
	  }
	} else {
	  value = nums.arrayGetNF(i + 1);
	  if (value.isRef()) {
	    Ref ref = value.getRef();
	    vec.resize(1);
	    vec[0].ref = ref;
	    refToParentMap.insert(std::pair<Ref, Parent*>(ref, &vec[0]));
	  } else {
	    error(errSyntaxError, -1, "Nums item at position {0:d} is wrong type ({1:s})", i + 1, value.getTypeName());
	  }
	}
      }
    } else {
      error(errSyntaxError, -1, "Nums array length is not a even ({0:d})", nums.arrayGetLength());
    }
  } else {
    error(errSyntaxError, -1, "Nums object is wrong type ({0:s})", nums.getTypeName());
  }
}


void StructTreeRoot::parentTreeAdd(const Ref &objectRef, StructElement *element)
{
  auto range = refToParentMap.equal_range(objectRef);
  for (auto it = range.first; it !=range.second; ++it)
    it->second->element = element;
}
