/*
    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 "metaxml.h"
#include "stylesxml.h"
#include <quazipfile.h>

QHash<QString, QString> *StylesXml::_p_hashNamespaceURI =
  new QHash<QString, QString>();

const QString &
StylesXml::getNamespaceURI(const QString &xml_namespace)
{
  if(_p_hashNamespaceURI->size() == 0)
    {
      _p_hashNamespaceURI->insert(
        "chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0");
      _p_hashNamespaceURI->insert("dc", "http://purl.org/dc/elements/1.1/");
      _p_hashNamespaceURI->insert(
        "dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0");
      _p_hashNamespaceURI->insert(
        "draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
      _p_hashNamespaceURI->insert(
        "fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
      _p_hashNamespaceURI->insert(
        "form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0");
      _p_hashNamespaceURI->insert("grddl",
                                  "http://www.w3.org/2003/g/data-view#");
      _p_hashNamespaceURI->insert("math", "http://www.w3.org/1998/Math/MathML");
      _p_hashNamespaceURI->insert(
        "meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0");
      _p_hashNamespaceURI->insert(
        "number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0");
      _p_hashNamespaceURI->insert(
        "of", "urn:oasis:names:tc:opendocument:xmlns:of:1.2");
      _p_hashNamespaceURI->insert(
        "office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
      _p_hashNamespaceURI->insert("ooo", "http://openoffice.org/2004/office");
      _p_hashNamespaceURI->insert(
        "presentation",
        "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0");
      _p_hashNamespaceURI->insert(
        "script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0");
      _p_hashNamespaceURI->insert(
        "style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
      _p_hashNamespaceURI->insert(
        "svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
      _p_hashNamespaceURI->insert(
        "table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0");
      _p_hashNamespaceURI->insert(
        "text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
      _p_hashNamespaceURI->insert("xhtml", "http://www.w3.org/1999/xhtml");
      _p_hashNamespaceURI->insert("xlink", "http://www.w3.org/1999/xlink");
      // * xmlns:ooow="http://openoffice.org/2004/writer"
      _p_hashNamespaceURI->insert("ooow", "http://openoffice.org/2004/writer");
      // * xmlns:oooc="http://openoffice.org/2004/calc"
      _p_hashNamespaceURI->insert("oooc", "http://openoffice.org/2004/calc");
      // * xmlns:dom="http://www.w3.org/2001/xml-events"
      _p_hashNamespaceURI->insert("dom", "http://www.w3.org/2001/xml-events");
      // * xmlns:rpt="http://openoffice.org/2005/report"
      _p_hashNamespaceURI->insert("rpt", "http://openoffice.org/2005/report");
      // * xmlns:tableooo="http://openoffice.org/2009/table"
      _p_hashNamespaceURI->insert("tableooo",
                                  "http://openoffice.org/2009/table");
      // * xmlns:css3t="http://www.w3.org/TR/css3-text/"
      _p_hashNamespaceURI->insert("css3t", "http://www.w3.org/TR/css3-text/");
    }
  return _p_hashNamespaceURI->operator[](xml_namespace);
}

StylesXml::StylesXml(QuaZip *p_quaZip)
{
  QuaZipFile outFile(p_quaZip);
  QuaZipNewInfo info("styles.xml");
  outFile.open(QIODevice::WriteOnly, info);
  QXmlStreamWriter writer(&outFile);
  writer.setAutoFormatting(true);

  this->WriteHeader(writer);
  this->WriteFontFaceDecls(writer);

  // <office:styles>
  this->WriteOfficeStyles(writer);

  // <office:automatic-styles>
  this->WriteAutomaticStyles(writer);

  // <office:master-styles>
  this->WriteMasterStyles(writer);
  writer.writeEndDocument();
  outFile.close();
}

StylesXml::~StylesXml()
{
}


void
StylesXml::WriteHeader(QXmlStreamWriter &writer)
{
  writer.writeStartDocument("1.0");
  /*
   * <?xml version="1.0" encoding="UTF-8"?> <office:document-styles
   * office:version="1.2" grddl
   * :transformation="http://docs.oasis-open.org/office/1.2/xslt/odf2rdf.xsl"
   * >
   */

  StylesXml::getNamespaceURI("office");
  QHash<QString, QString>::iterator i;
  for(i = StylesXml::_p_hashNamespaceURI->begin();
      i != StylesXml::_p_hashNamespaceURI->end();
      ++i)
    {
      writer.writeNamespace(i.value(), i.key());
    }
  writer.writeStartElement(StylesXml::getNamespaceURI("office"),
                           "document-styles");
  writer.writeAttribute(StylesXml::getNamespaceURI("office"), "version", "1.2");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("grddl"),
    "transformation",
    "http://docs.oasis-open.org/office/1.2/xslt/odf2rdf.xsl");
}

void
StylesXml::WriteFontFaceDecls(QXmlStreamWriter &writer)
{
  /*
   *
   * <office:font-face-decls>
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("office"),
                           "font-face-decls");
  /*
   * <style:font-face style:name="Arial" svg:font-family="Arial"
   * style:font-family-generic="swiss" style:font-pitch="variable"/>
   */
  // Arial
  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "font-face");
  writer.writeAttribute(StylesXml::getNamespaceURI("style"), "name", "Arial");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("svg"), "font-family", "Arial");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "font-family-generic", "swiss");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "font-pitch", "variable");
  writer.writeEndElement();

  /*
   * </office:font-face-decls>
   */
  writer.writeEndElement();
}

void
StylesXml::WriteOfficeStyles(QXmlStreamWriter &writer)
{
  // <office:styles>
  writer.writeStartElement(MetaXml::getNamespaceURI("office"), "styles");

  /*
   * <number:number-style style:name="N0"><number:number
   * number:min-integer-digits="1"/></number:number-style>
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("number"), "number-style");
  writer.writeAttribute(StylesXml::getNamespaceURI("style"), "name", "N0");
  writer.writeStartElement(MetaXml::getNamespaceURI("number"), "number");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("number"), "min-integer-digits", "1");
  writer.writeEndElement();
  writer.writeEndElement();

  /*
   * <number:date-style
   * style:name="N36"><number:day/><number:text>/</number
   * :text><number:month/><number:text>/</number:text> <number:year/>
   * </number:date-style>
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("number"), "date-style");
  writer.writeAttribute(StylesXml::getNamespaceURI("style"), "name", "N36");
  writer.writeStartElement(MetaXml::getNamespaceURI("number"), "day");
  writer.writeEndElement();
  writer.writeStartElement(MetaXml::getNamespaceURI("number"), "text");
  writer.writeCharacters("/");
  writer.writeEndElement();
  writer.writeStartElement(MetaXml::getNamespaceURI("number"), "month");
  writer.writeEndElement();
  writer.writeStartElement(MetaXml::getNamespaceURI("number"), "text");
  writer.writeCharacters("/");
  writer.writeEndElement();
  writer.writeStartElement(MetaXml::getNamespaceURI("number"), "year");
  writer.writeEndElement();
  writer.writeEndElement();

  /*
   *
   *
   *
   *
   *
   *
   */
  /*
   * <style:style style:name="Default" style:family="table-cell"
   * style:data-style-name="N0">
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "style");
  writer.writeAttribute(StylesXml::getNamespaceURI("style"), "name", "Default");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "family", "table-cell");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "data-style-name", "N0");
  /*
   * <style:table-cell-properties style:vertical-align="automatic"
   * fo:background-color="transparent" />
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("style"),
                           "table-cell-properties");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "vertical-align", "automatic");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("fo"), "background-color", "transparent");
  writer.writeEndElement();

  /*
   * <style:text-properties fo:color="#000000" style:font-name="Calibri"
   * style:font-name-asian="Calibri" style:font-name-complex="Calibri"
   * fo:font-size="11pt" style:font-size-asian="11pt"
   * style:font-size-complex="11pt" />
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("style"),
                           "text-properties");
  writer.writeAttribute(StylesXml::getNamespaceURI("fo"), "color", "#000000");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "font-name", "Arial");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "font-name-asian", "Arial");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "font-name-complex", "Arial");
  writer.writeAttribute(StylesXml::getNamespaceURI("fo"), "font-size", "11pt");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "font-size-asian", "11pt");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "font-size-complex", "11pt");
  writer.writeEndElement();

  // </style:style>
  writer.writeEndElement();

  // <style:default-style style:family="graphic">
  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "default-style");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "family", "graphic");
  /*
   * <style:graphic-properties draw:fill="solid" draw:fill-color="#4f81bd"
   * draw:opacity="100%" draw:stroke="solid" svg:stroke-width="0.02778in"
   * svg:stroke-color="#385d8a" svg:stroke-opacity="100%" />
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("style"),
                           "graphic-properties");
  writer.writeAttribute(StylesXml::getNamespaceURI("draw"), "fill", "solid");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("draw"), "fill-color", "#4f81bd");
  writer.writeAttribute(StylesXml::getNamespaceURI("draw"), "opacity", "100%");
  writer.writeAttribute(StylesXml::getNamespaceURI("draw"), "stroke", "solid");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("svg"), "stroke-width", "0.02778in");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("svg"), "stroke-color", "#385d8a");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("svg"), "stroke-opacity", "100%");
  writer.writeEndElement();

  // </style:default-style>
  writer.writeEndElement();

  writer.writeEndElement();
}

void
StylesXml::WriteAutomaticStyles(QXmlStreamWriter &writer)
{
  /*
   *
   * <style:header-style> <style:header-footer-properties
   * fo:min-height="0.45in" fo:margin-left="0.7in" fo:margin-right="0.7in"
   * fo:margin-bottom="0in" /> </style:header-style> <style:footer-style>
   * <style:header-footer-properties fo:min-height="0.45in"
   * fo:margin-left="0.7in" fo:margin-right="0.7in" fo:margin-top="0in" />
   * </style:footer-style> </style:page-layout> </office:automatic-styles>
   */
  /*
   * <office:automatic-styles> <style:page-layout style:name="pm1">
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("office"),
                           "automatic-styles");

  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "page-layout");
  writer.writeAttribute(StylesXml::getNamespaceURI("style"), "name", "pm1");
  /*
   * <style:page-layout-properties fo:margin-top="0.3in"
   * fo:margin-bottom="0.3in" fo:margin-left="0.7in"
   * fo:margin-right="0.7in" style:table-centering="none"
   * style:print="objects charts drawings" />
   */
  writer.writeStartElement(MetaXml::getNamespaceURI("style"),
                           "page-layout-properties");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("fo"), "margin-top", "0.3in");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("fo"), "margin-bottom", "0.3in");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("fo"), "margin-left", "0.7in");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("fo"), "margin-right", "0.7in");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "table-centering", "none");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "print", "objects charts drawings");
  writer.writeEndElement();

  writer.writeEndElement();
  writer.writeEndElement();
}


void
StylesXml::WriteMasterStyles(QXmlStreamWriter &writer)
{
  /*
   *
   *
   *
   */
  //<office:master-styles>
  writer.writeStartElement(MetaXml::getNamespaceURI("office"), "master-styles");
  //<style:master-page style:name="mp1" style:page-layout-name="pm1">
  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "master-page");
  writer.writeAttribute(StylesXml::getNamespaceURI("style"), "name", "mp1");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "page-layout-name", "pm1");
  //<style:header />
  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "header");
  writer.writeEndElement();

  //<style:header-left style:display="false" />
  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "header-left");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "display", "false");
  writer.writeEndElement();

  //<style:footer />
  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "footer");
  writer.writeEndElement();

  //<style:footer-left style:display="false" />
  writer.writeStartElement(MetaXml::getNamespaceURI("style"), "footer-left");
  writer.writeAttribute(
    StylesXml::getNamespaceURI("style"), "display", "false");
  writer.writeEndElement();

  //</style:master-page>
  writer.writeEndElement();

  //</office:master-styles>
  writer.writeEndElement();
}
