/* poppler-outline.cc: qt interface to poppler
 *
 * Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
 * Copyright (C) 2019 Oliver Sander <oliver.sander@tu-dresden.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <poppler-qt5.h>
#include <poppler-link.h>

#include "poppler-private.h"
#include "poppler-outline-private.h"

#include "Link.h"
#include "Outline.h"

namespace Poppler {

OutlineItem::OutlineItem() : m_data{new OutlineItemData{nullptr, nullptr}} {}

OutlineItem::OutlineItem(OutlineItemData *data) : m_data{data} {}

OutlineItem::~OutlineItem()
{
  delete m_data;
  m_data = nullptr;
}

OutlineItem::OutlineItem(const OutlineItem &other) : m_data{new OutlineItemData{*other.m_data}} {}

OutlineItem &OutlineItem::operator=(const OutlineItem &other)
{
  auto *data = new OutlineItemData{*other.m_data};
  qSwap(m_data, data);
  delete data;

  return *this;
}

OutlineItem::OutlineItem(OutlineItem &&other) : m_data{other.m_data}
{
  other.m_data = nullptr;
}

OutlineItem &OutlineItem::operator=(OutlineItem &&other)
{
  qSwap(m_data, other.m_data);

  return *this;
}

bool OutlineItem::isNull() const
{
  return !m_data->data;
}

QString OutlineItem::name() const
{
  QString &name = m_data->name;

  if (name.isEmpty()) {
    if (const ::OutlineItem *data = m_data->data) {
      name = unicodeToQString(data->getTitle(), data->getTitleLength());
    }
  }

  return name;
}

bool OutlineItem::isOpen() const
{
  bool isOpen = false;

  if (const ::OutlineItem *data = m_data->data) {
    isOpen = data->isOpen();
  }

  return isOpen;
}

QSharedPointer<const LinkDestination> OutlineItem::destination() const
{
  QSharedPointer<const LinkDestination> &destination = m_data->destination;

  if (!destination) {
    if (const ::OutlineItem *data = m_data->data) {
      if (const ::LinkAction *action = data->getAction()) {
	if (action->getKind() == actionGoTo) {
	  const auto *linkGoTo = static_cast<const LinkGoTo *>(action);
	  destination.reset(new LinkDestination(LinkDestinationData(linkGoTo->getDest(), linkGoTo->getNamedDest(), m_data->documentData, false)));
	} else if (action->getKind() == actionGoToR) {
	  const auto *linkGoToR = static_cast<const LinkGoToR *>(action);
	  const bool external = linkGoToR->getFileName() != nullptr;
	  destination.reset(new LinkDestination(LinkDestinationData(linkGoToR->getDest(), linkGoToR->getNamedDest(), m_data->documentData, external)));
	}
      }
    }
  }

  return destination;
}

QString OutlineItem::externalFileName() const
{
  QString &externalFileName = m_data->externalFileName;

  if (externalFileName.isEmpty()) {
    if (const ::OutlineItem *data = m_data->data) {
      if (const ::LinkAction *action = data->getAction()) {
	if (action->getKind() == actionGoToR) {
	  if (const GooString *fileName = static_cast<const LinkGoToR *>(action)->getFileName()) {
	    externalFileName = UnicodeParsedString(fileName);
	  }
	}
      }
    }
  }

  return externalFileName;
}

QString OutlineItem::uri() const
{
  QString &uri = m_data->uri;

  if (uri.isEmpty()) {
    if (const ::OutlineItem *data = m_data->data) {
      if (const ::LinkAction *action = data->getAction()) {
	if (action->getKind() == actionURI) {
	  uri = UnicodeParsedString(static_cast<const LinkURI *>(action)->getURI());
	}
      }
    }
  }

  return uri;
}

bool OutlineItem::hasChildren() const
{
  bool result = false;

  if (::OutlineItem *data = m_data->data) {
    result = data->hasKids();
  }

  return result;
}

QVector<OutlineItem> OutlineItem::children() const
{
  QVector<OutlineItem> result;

  if (::OutlineItem *data = m_data->data) {
    data->open();
    if (const std::vector<::OutlineItem*> *kids = data->getKids()) {
      for (void *kid : *kids) {
	result.push_back(OutlineItem{new OutlineItemData{static_cast<::OutlineItem *>(kid), m_data->documentData}});
      }
    }
  }

  return result;
}

}
