/*
    libodsstream is a library to read and write ODS documents as streams
    Copyright (C) 2013  Olivier Langella <Olivier.Langella@moulon.inra.fr>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "../../config.h"
#include "metaxml.h"
#include <QDateTime>
#include "../../odsexception.h"
#include <quazipfile.h>

#define LIBODS_GENERATOR_NAME LIBODSSTREAM_LIB_NAME "/" LIBODSSTREAM_VERSION


std::map<const QString, const QString> MetaXml::_hash_namespace_uri;

const QString &
MetaXml::getNamespaceURI(const QString &xml_namespace)
{
  if(_hash_namespace_uri.size() == 0)
    {
      _hash_namespace_uri.insert(std::make_pair(
        "anim", "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "db", "urn:oasis:names:tc:opendocument:xmlns:database:1.0"));
      _hash_namespace_uri.insert(
        std::make_pair("dc", "http://purl.org/dc/elements/1.1/"));
      _hash_namespace_uri.insert(std::make_pair(
        "dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0"));
      _hash_namespace_uri.insert(
        std::make_pair("grddl", "http://www.w3.org/2003/g/data-view#"));
      _hash_namespace_uri.insert(
        std::make_pair("math", "http://www.w3.org/1998/Math/MathML"));
      _hash_namespace_uri.insert(std::make_pair(
        "meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"));
      _hash_namespace_uri.insert(
        std::make_pair("of", "urn:oasis:names:tc:opendocument:xmlns:of:1.2"));
      _hash_namespace_uri.insert(std::make_pair(
        "office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0"));
      _hash_namespace_uri.insert(
        std::make_pair("ooo", "http://openoffice.org/2004/office"));
      _hash_namespace_uri.insert(std::make_pair(
        "presentation",
        "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "smil", "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0"));
      _hash_namespace_uri.insert(std::make_pair(
        "text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0"));
      _hash_namespace_uri.insert(
        std::make_pair("xforms", "http://www.w3.org/2002/xforms"));
      _hash_namespace_uri.insert(
        std::make_pair("calcext",
                       "urn:org:documentfoundation:names:experimental:calc:"
                       "xmlns:calcext:1.0"));
      _hash_namespace_uri.insert(
        std::make_pair("xhtml", "http://www.w3.org/1999/xhtml"));
      _hash_namespace_uri.insert(
        std::make_pair("xlink", "http://www.w3.org/1999/xlink"));
    }
  auto it = _hash_namespace_uri.find(xml_namespace);
  if(it != _hash_namespace_uri.end())
    {
      return it->second;
    }
  else
    {
      throw OdsException(
        QObject::tr("XML namespace %1 not defined in MetaXml object")
          .arg(xml_namespace));
    }
}


MetaXml::MetaXml(QuaZip *p_quaZip) : _p_quaZip(p_quaZip)
{
  QuaZipFile outFile(_p_quaZip);
  QuaZipNewInfo info("meta.xml");
  outFile.open(QIODevice::WriteOnly, info);
  QXmlStreamWriter *p_writer = new QXmlStreamWriter(&outFile);
  p_writer->setAutoFormatting(true);

  this->WriteHeader(p_writer);

  p_writer->writeStartElement(MetaXml::getNamespaceURI("office"), "meta");

  /*
   * see RFC2616, or 3.1.1 in the oasis doc : meta:generator
   */
  p_writer->writeStartElement(MetaXml::getNamespaceURI("meta"), "generator");
  p_writer->writeCharacters(LIBODS_GENERATOR_NAME);
  p_writer->writeEndElement();

  QDateTime currentdate(QDateTime::currentDateTime());

  p_writer->writeStartElement(MetaXml::getNamespaceURI("meta"),
                              "creation-date");
  p_writer->writeCharacters(currentdate.toString("yyyy-MM-dd'T'HH:mm:ss"));
  p_writer->writeEndElement();

  p_writer->writeStartElement(MetaXml::getNamespaceURI("dc"), "date");
  p_writer->writeCharacters(currentdate.toString("yyyy-MM-dd'T'HH:mm:ss"));
  p_writer->writeEndElement();

  p_writer->writeStartElement(MetaXml::getNamespaceURI("meta"),
                              "editing-cycles");
  p_writer->writeCharacters("1");
  p_writer->writeEndElement();

  p_writer->writeStartElement(MetaXml::getNamespaceURI("meta"),
                              "editing-duration");
  p_writer->writeCharacters("PT0.602S");
  p_writer->writeEndElement();

  p_writer->writeEndDocument();

  delete p_writer;

  outFile.close();
}

void
MetaXml::WriteHeader(QXmlStreamWriter *p_writer)
{
  p_writer->writeStartDocument("1.0");
  MetaXml::getNamespaceURI("office");

  std::map<const QString, const QString>::const_iterator it =
    MetaXml::_hash_namespace_uri.begin();
  while(it != MetaXml::_hash_namespace_uri.end())
    {
      p_writer->writeNamespace(QString(it->second), it->first);
      it++;
    }

  // <manifest:manifest
  // xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"
  // manifest:version="1.2" >
  p_writer->writeStartElement(MetaXml::getNamespaceURI("office"),
                              "document-meta");
  p_writer->writeAttribute(
    MetaXml::getNamespaceURI("office"), "version", "1.2");
  // writer.setPrefix("manifest", namespaceURI);
  // writer.setDefaultNamespace(namespaceURI);
  // writer.writeStartElement("mzXML");
}


MetaXml::~MetaXml()
{
}
