/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libepubgen project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "EPUBCSSSink.h"
#include "EPUBHTMLGenerator.h"
#include "EPUBGenerator.h"
#include "EPUBXMLSink.h"

namespace libepubgen
{

using librevenge::RVNGPropertyFactory;
using librevenge::RVNGPropertyList;
using librevenge::RVNGString;

EPUBGenerator::EPUBGenerator(EPUBPackage *const package, const EPUBSplitMethod split)
  : m_package(package)
  , m_manifest()
  , m_htmlManager(m_manifest)
  , m_imageManager(m_manifest)
  , m_listStyleManager()
  , m_paragraphStyleManager()
  , m_spanStyleManager()
  , m_tableStyleManager()
  , m_stylesheetPath("OEBPS/styles/stylesheet.css")
  , m_documentProps()
  , m_metadata()
  , m_currentHtml()
  , m_splitGuard(split)
{
}

EPUBGenerator::~EPUBGenerator()
{
}

void EPUBGenerator::startDocument(const RVNGPropertyList &props)
{
  m_documentProps = props;

  startNewHtmlFile();

  m_manifest.insert(EPUBPath("OEBPS/toc.ncx"), "application/x-dtbncx+xml", "toc.ncx");
  m_manifest.insert(m_stylesheetPath, "text/css", "stylesheet.css");
}

void EPUBGenerator::endDocument()
{
  if (bool(m_currentHtml))
  {
    endHtmlFile();
    m_currentHtml->endDocument();
  }

  writeContainer();
  writeRoot();
  writeNavigation();
  writeStylesheet();
  m_htmlManager.writeTo(*m_package);
  m_imageManager.writeTo(*m_package);
}

void EPUBGenerator::setDocumentMetaData(const RVNGPropertyList &props)
{
  m_metadata = props;
}

void EPUBGenerator::startNewHtmlFile()
{
  // close the current HTML file
  if (bool(m_currentHtml))
  {
    endHtmlFile();
    m_currentHtml->endDocument();
  }

  m_splitGuard.onSplit();

  m_currentHtml = m_htmlManager.create(m_imageManager, m_listStyleManager, m_paragraphStyleManager, m_spanStyleManager, m_tableStyleManager, m_stylesheetPath);

  // restore state in the new file
  m_currentHtml->startDocument(m_documentProps);
  m_currentHtml->setDocumentMetaData(m_metadata);

  startHtmlFile();
}

const EPUBHTMLGeneratorPtr_t &EPUBGenerator::getHtml() const
{
  return m_currentHtml;
}

const EPUBSplitGuard &EPUBGenerator::getSplitGuard() const
{
  return m_splitGuard;
}

EPUBSplitGuard &EPUBGenerator::getSplitGuard()
{
  return m_splitGuard;
}

void EPUBGenerator::writeContainer()
{
  EPUBXMLSink sink;

  RVNGPropertyList containerAttrs;
  containerAttrs.insert("version", "1.0");
  containerAttrs.insert("xmlns", "urn:oasis:names:tc:opendocument:xmlns:container");

  sink.openElement("container", containerAttrs);
  sink.openElement("rootfiles");

  RVNGPropertyList rootfileAttrs;
  rootfileAttrs.insert("full-path", "OEBPS/content.opf");
  rootfileAttrs.insert("media-type", "application/oebps-package+xml");

  sink.insertEmptyElement("rootfile", rootfileAttrs);

  sink.closeElement("rootfiles");
  sink.closeElement("container");

  sink.writeTo(*m_package, "META-INF/container.xml");
}

void EPUBGenerator::writeNavigation()
{
  const EPUBPath path("OEBPS/toc.ncx");
  EPUBXMLSink sink;

  RVNGPropertyList ncxAttrs;
  ncxAttrs.insert("xmlns", "http://www.daisy.org/z3986/2005/ncx/");
  ncxAttrs.insert("version", "2005-1");

  sink.openElement("ncx", ncxAttrs);

  sink.openElement("head");
  RVNGPropertyList metaAttrs;
  metaAttrs.insert("name", "");
  metaAttrs.insert("content", "");
  metaAttrs.insert("scheme", "");
  sink.insertEmptyElement("meta", metaAttrs);
  sink.closeElement("head");
  sink.openElement("docTitle");
  sink.openElement("text");
  sink.closeElement("text");
  sink.closeElement("docTitle");

  sink.openElement("navMap");
  m_htmlManager.writeTocTo(sink, path);
  sink.closeElement("navMap");

  sink.closeElement("ncx");

  sink.writeTo(*m_package, path.str().c_str());
}

void EPUBGenerator::writeStylesheet()
{
  EPUBCSSSink sink;

  m_listStyleManager.send(sink);
  m_paragraphStyleManager.send(sink);
  m_spanStyleManager.send(sink);
  m_tableStyleManager.send(sink);

  sink.writeTo(*m_package, m_stylesheetPath.str().c_str());
}

void EPUBGenerator::writeRoot()
{
  EPUBXMLSink sink;

  const RVNGString uniqueId("unique-identifier");

  RVNGPropertyList packageAttrs;
  packageAttrs.insert("xmlns", "http://www.idpf.org/2007/opf");
  packageAttrs.insert("xmlns:dc", "http://purl.org/dc/elements/1.1/");
  packageAttrs.insert("xmlns:dcterms", "http://purl.org/dc/terms/");
  packageAttrs.insert("xmlns:opf", "http://www.idpf.org/2007/opf");
  packageAttrs.insert("version", RVNGPropertyFactory::newStringProp("2.0"));
  packageAttrs.insert("unique-identifier", uniqueId);

  sink.openElement("package", packageAttrs);

  sink.openElement("metadata");

  RVNGPropertyList identifierAttrs;
  identifierAttrs.insert("id", uniqueId);
  sink.insertEmptyElement("dc:identifier", identifierAttrs);

  sink.openElement("dc:title");
  sink.closeElement("dc:title");
  sink.openElement("dc:language");
  sink.closeElement("dc:language");

  sink.closeElement("metadata");

  sink.openElement("manifest");
  m_manifest.writeTo(sink);
  sink.closeElement("manifest");

  RVNGPropertyList spineAttrs;
  spineAttrs.insert("toc", "toc.ncx");

  sink.openElement("spine", spineAttrs);
  m_htmlManager.writeSpineTo(sink);
  sink.closeElement("spine");

  sink.openElement("guide");
  sink.closeElement("guide");

  sink.closeElement("package");

  sink.writeTo(*m_package, "OEBPS/content.opf");
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
