/*
    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 <quazip/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("UTF-8", "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"), "master-page");
    /*
     * <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> <style:master-page style:name="mp1"
     * style:page-layout-name="pm1"> <style:header /> <style:header-left
     * style:display="false" /> <style:footer /> <style:footer-left
     * style:display="false" /> </style:master-page> </office:master-styles>
     */
    writer.writeStartElement(MetaXml::getNamespaceURI("office"), "master-styles");
    writer.writeStartElement(MetaXml::getNamespaceURI("style"), "master-page");
    writer.writeAttribute(StylesXml::getNamespaceURI("style"),"name", "mp1");
    writer.writeAttribute(StylesXml::getNamespaceURI("style"),"page-layout-name", "pm1");
    writer.writeStartElement(MetaXml::getNamespaceURI("style"), "header");
    writer.writeEndElement();
    writer.writeStartElement(MetaXml::getNamespaceURI("style"),"header-left");
    writer.writeAttribute(StylesXml::getNamespaceURI("style"),"display", "false");
    writer.writeEndElement();
    writer.writeStartElement(MetaXml::getNamespaceURI("style"),"footer-left");
    writer.writeAttribute(StylesXml::getNamespaceURI("style"),"display", "false");
    writer.writeEndElement();
    writer.writeEndElement();
    writer.writeEndElement();
}


