/*
    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 <algorithm>
#include "contentxml.h"
#include "metaxml.h"
#include "../odsexception.h"

QString ContentXml::_xsdNamespaceURI = "http://www.w3.org/2001/XMLSchema";
QString ContentXml::_xsiNamespaceURI = "http://www.w3.org/2001/XMLSchema-instance";

ContentXml::ContentXml(QuaZip * p_quaZip): _outFile(p_quaZip) {
    QuaZipNewInfo info("content.xml");
    _outFile.open(QIODevice::WriteOnly,info);
    _p_writer = new QXmlStreamWriter(&_outFile);
    _p_writer->setAutoFormatting(true);
    this->WriteHeader();
}

ContentXml::~ContentXml() {

}

void ContentXml::WriteHeader() {
    _tableRowStarted = false;
    _tableStarted = false;
    _p_writer->writeStartDocument("UTF-8", "1.0");
    /*
     * <office:document-content office:version="1.2"
     * xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
     * xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
     * xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
     * xmlns:db="urn:oasis:names:tc:opendocument:xmlns:database:1.0"
     * xmlns:dc="http://purl.org/dc/elements/1.1/"
     * xmlns:dom="http://www.w3.org/2001/xml-events"
     * xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
     * xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
     * xmlns:fo
     * ="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
     * xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
     * xmlns:grddl="http://www.w3.org/2003/g/data-view#"
     * xmlns:math="http://www.w3.org/1998/Math/MathML"
     * xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
     * xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
     * xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2"
     * xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
     * xmlns:ooo="http://openoffice.org/2004/office"
     * xmlns:oooc="http://openoffice.org/2004/calc"
     * xmlns:ooow="http://openoffice.org/2004/writer" xmlns:presentation=
     * "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
     * xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
     * xmlns:
     * smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"
     * xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
     * xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
     * xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
     * xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
     * xmlns:xforms="http://www.w3.org/2002/xforms"
     * xmlns:xhtml="http://www.w3.org/1999/xhtml"
     * xmlns:xlink="http://www.w3.org/1999/xlink"
     * xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     */
    MetaXml::getNamespaceURI("office");
    QHash<QString, QString>::iterator i;
    for (i = MetaXml::_p_hashNamespaceURI->begin(); i != MetaXml::_p_hashNamespaceURI->end(); ++i) {
        _p_writer->writeNamespace(i.value(), i.key());
    }
    // xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    _p_writer->writeNamespace(_xsdNamespaceURI,"xsd" );

    // xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    _p_writer->writeNamespace(_xsiNamespaceURI, "xsi");

    _p_writer->writeStartElement(MetaXml::getNamespaceURI("office"), "document-content");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"), "version", "1.2");



    // <office:scripts/>
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("office"), "scripts");
    _p_writer->writeEndElement();

    // <office:font-face-decls>
    writeFontFaceDecls();

}


void ContentXml::writeFontFaceDecls() {
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("office"), "font-face-decls");
    /**
     * <style:font-face style:font-family-generic="swiss"
     * style:font-pitch="variable" style:name="Arial"
     * svg:font-family="Arial"/>
     * */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "font-face");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"font-family-generic", "swiss");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"font-pitch", "variable");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "name","Arial");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("svg"),"font-family", "Arial");
    _p_writer->writeEndElement();

    _p_writer->writeEndElement();
}


void ContentXml::startSpreadsheet() {

    if (_spreadsheet_started) return;
    _spreadsheet_started = true;

    // <office:body>
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("office"), "body");
    // <office:spreadsheet>
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("office"), "spreadsheet");
}

void ContentXml::writeAutomaticStyles() {

    if (_automatic_styles_writed) return;
    _automatic_styles_writed = true;

    /*
     * <office:automatic-styles>
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     * </office:automatic-styles>
     */
    /*
     *
     * <office:automatic-styles>
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("office"), "automatic-styles");
    /*
     * <style:style style:name="ce1" style:family="table-cell"
     * style:parent-style-name="Default" style:data-style-name="N0" />
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "style");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "name","ce1");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "family","table-cell");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"parent-style-name", "Default");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"data-style-name", "N0");
    _p_writer->writeEndElement();

    /*
     * <style:style style:name="ce2" style:family="table-cell"
     * style:parent-style-name="Default" style:data-style-name="N36" />
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "style");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "name","ce2");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "family","table-cell");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"parent-style-name", "Default");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"data-style-name", "N36");
    _p_writer->writeEndElement();
    // <style:style style:name="co1" style:family="table-column">
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "style");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "name","co1");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "family","table-column");

    /*
     * <style:table-column-properties fo:break-before="auto"
     * style:column-width="2.27541666666667cm" />
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "table-column-properties");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("fo"), "break-before","auto");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"column-width", "2.27541666666667cm");
    _p_writer->writeEndElement();
    // </style:style>
    _p_writer->writeEndElement();

    // <style:style style:name="co2" style:family="table-column">
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "style");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "name","co2");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "family","table-column");
    // <style:table-column-properties
    // fo:break-before="auto" style:column-width="2.11666666666667cm" />
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "table-column-properties");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("fo"), "break-before","auto");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"column-width", "2.27541666666667cm");
    _p_writer->writeEndElement();
    // </style:style>
    _p_writer->writeEndElement();
    // <style:style style:name="ro1" style:family="table-row">
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "style");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "name","ro1");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "family","table-row");

    // <style:table-row-properties
    // style:row-height="15pt" style:use-optimal-row-height="true"
    // fo:break-before="auto" />
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "table-row-properties");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"row-height", "15pt");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"use-optimal-row-height", "true");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("fo"), "break-before","auto");
    _p_writer->writeEndElement();
    // </style:style>
    _p_writer->writeEndElement();

    // <style:style style:name="ta1" style:family="table"
    // style:master-page-name="mp1">
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "style");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "name","ta1");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "family","table");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"master-page-name", "mp1");
    // <style:table-properties table:display="true"
    // style:writing-mode="lr-tb" />
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "table-properties");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"display", "true");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"writing-mode", "lr-tb");
    _p_writer->writeEndElement();

    // </style:style>
    _p_writer->writeEndElement();

    /*
     *
    <style:style style:name="ce3" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N0">
    <style:table-cell-properties fo:background-color="#ffff00"/>
    <style:text-properties fo:color="#800000"/>
    </style:style>
    */

    for (unsigned int i=0; i < _style2write.size(); i++) {
        _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "style");
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "name",_style_ref_list[i]->_ref_str);
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"), "family","table-cell");
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"parent-style-name", "Default");
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("style"),"data-style-name", "N0");

        if (_style2write[i]._background_color.isValid()) {
            _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "table-cell-properties");
            _p_writer->writeAttribute(MetaXml::getNamespaceURI("fo"), "background-color",_style2write[i]._background_color.name());
            _p_writer->writeEndElement();
        }
        if (_style2write[i]._text_color.isValid()) {
            _p_writer->writeStartElement(MetaXml::getNamespaceURI("style"), "text-properties");
            _p_writer->writeAttribute(MetaXml::getNamespaceURI("fo"), "color",_style2write[i]._text_color.name());
            _p_writer->writeEndElement();
        }

        _p_writer->writeEndElement();
    }
    _p_writer->writeEndElement();
}

void ContentXml::close() {

    writeAutomaticStyles();
    startSpreadsheet();

    _p_writer->writeEndDocument();

    this->_outFile.close();

    delete _p_writer;

}

void ContentXml::writeSheet(const QString & tableName) {

    writeAutomaticStyles();
    startSpreadsheet();

    if (_tableRowStarted) {
        _p_writer->writeEndElement();
    }
    if (_tableStarted) {
        _p_writer->writeEndElement();
    }
    _tableStarted = true;
    _tableRowStarted = false;

    /*
     * <table:table table:name="Feuille1" table:style-name="ta1"
     * table:print="false">
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"), "name", tableName);
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ta1");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"), "print","false");

    /*
     * <table:table-column table:style-name="co1"
     * table:default-cell-style-name="ce1" />
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-column");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "co1");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"default-cell-style-name", "ce1");
    _p_writer->writeEndElement();

}

void ContentXml::writeLine() {

    writeAutomaticStyles();
    startSpreadsheet();

    if (_tableStarted == false) {
        writeSheet();
    }
    if (_tableRowStarted) {
        _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-cell");
        _p_writer->writeEndElement();
        _p_writer->writeEndElement();
    }
    _tableRowStarted = true;
    /*
     * <table:table-row table:style-name="ro1">
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-row");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ro1");

}

void ContentXml::writeSheet() {
    writeSheet("default");
}

void ContentXml::writeCell(double value, const QString & annotation) {
    writeCellFloat(QString::number(value, 'e', 20), QString::number(value, 'g', 20), annotation);
}

void ContentXml::writeCell(int value, const QString & annotation) {
    QString representation(QString::number(value));
    writeCellFloat(representation, representation, annotation);
}


void ContentXml::writeCellPercentage(double value, const QString & annotation) {
    QString representation(QString("%1 %").arg(value*100));
    writeAutomaticStyles();
    startSpreadsheet();

    if (_tableRowStarted == false) {
        writeLine();
    }
    /*
     * <table:table-cell office:value-type="percentage" office:value="0.5" calcext:value-type="percentage">
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-cell");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value-type", "percentage");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value", QString::number(value, 'f', 5));
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("calcext"),"value-type", "percentage");
    // table:style-name="ce1"
    if (_current_style_ref != nullptr) {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", _current_style_ref->_ref_str);
    }
    else {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ce1");
    }
    writeAnnotation (annotation);
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "p");
    //<text:p>50,00 %</text:p></table:table-cell>
    _p_writer->writeCharacters(representation);
    _p_writer->writeEndElement();

    /*
     * </table:table-cell>
     */
    _p_writer->writeEndElement();
    /*
     * </table:table-row> </table:table> </office:spreadsheet>
     * </office:body>
     */
}


void ContentXml::writeCellFloat(const QString & value,const QString & representation, const QString & annotation) {

    writeAutomaticStyles();
    startSpreadsheet();

    if (_tableRowStarted == false) {
        writeLine();
    }
    /*
     * <table:table-cell office:value-type="float" office:value="45">
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-cell");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value-type", "float");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value", value);
    // table:style-name="ce1"
    if (_current_style_ref != nullptr) {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", _current_style_ref->_ref_str);
    }
    else {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ce1");
    }
    /*
     * <text:p>45</text:p>
     */
    writeAnnotation (annotation);
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "p");
    _p_writer->writeCharacters(representation);
    _p_writer->writeEndElement();

    /*
     * </table:table-cell>
     */
    _p_writer->writeEndElement();
    /*
     * </table:table-row> </table:table> </office:spreadsheet>
     * </office:body>
     */
}


void ContentXml::writeEmptyCell(const QString & annotation) {

    writeAutomaticStyles();
    startSpreadsheet();

    if (_tableRowStarted == false) {
        writeLine();
    }
    /*
     * <table:table-cell office:value-type="string">
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-cell");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value-type", "string");
    // table:style-name="ce1"
    if (_current_style_ref != nullptr) {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", _current_style_ref->_ref_str);
    }
    else {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ce1");
    }
    /*
     * <text:p>45</text:p>
     */
    writeAnnotation (annotation);
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "p");
    _p_writer->writeCharacters("");
    _p_writer->writeEndElement();

    _p_writer->writeEndElement();

}


void ContentXml::writeAnnotation(const QString & annotation) {
    //<office:annotation draw:style-name="gr1" draw:text-style-name="P2"
    //svg:width="28.99mm" svg:height="10.69mm" svg:x="96.48mm" svg:y="0mm"
//draw:caption-point-x="-6.1mm" draw:caption-point-y="10.68mm"><dc:date>2016-08-19T00:00:00</dc:date>
//<text:p text:style-name="P1">Ceci est un commentaire</text:p>
//</office:annotation>
    if (!annotation.isEmpty()) {
        _p_writer->writeStartElement(MetaXml::getNamespaceURI("office"), "annotation");
        _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "p");
        _p_writer->writeCharacters(annotation);
        _p_writer->writeEndElement();

        _p_writer->writeEndElement();//annotation
    }
}

void ContentXml::writeCell(const QString & value, const QString & annotation) {

    writeAutomaticStyles();
    startSpreadsheet();

    if (_tableRowStarted == false) {
        writeLine();
    }
    /*
     * <table:table-cell office:value-type="string">
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-cell");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value-type", "string");
    // table:style-name="ce1"


    if (_current_style_ref != nullptr) {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", _current_style_ref->_ref_str);
    }
    else {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ce1");
    }
    /*
     * <text:p>45</text:p>
     */
    writeAnnotation (annotation);
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "p");
    _p_writer->writeCharacters(value);
    _p_writer->writeEndElement();

    _p_writer->writeEndElement();

}

void ContentXml::writeCell(const QDateTime & cal, const QString & annotation) {

    writeAutomaticStyles();
    startSpreadsheet();


    if (_tableRowStarted == false) {
        writeLine();
    }
    //cal..setTimezone(0);
    /*
     * <table:table-cell office:value-type="date"
     * office:date-value="2011-07-16"
     * ><text:p>16/07/11</text:p></table:table-cell>
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-cell");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value-type", "date");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"date-value", cal.toString("yyyy-MM-dd'T'HH:mm:ss"));
    // table:style-name="ce1"
    if (_current_style_ref != nullptr) {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", _current_style_ref->_ref_str);
    }
    else {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ce2");
    }
    /*
     * <text:p>45</text:p>
     */
    writeAnnotation (annotation);
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "p");
    // writer.writeCharacters(cal.getDay()+"/"+cal.getMonth()+"/11");
    _p_writer->writeCharacters(cal.toString("dd/MM/yyyy"));
    _p_writer->writeEndElement();

    /*
     * </table:table-cell>
     */
    _p_writer->writeEndElement();
    /*
     * </table:table-row> </table:table> </office:spreadsheet>
     * </office:body>
     */

}

void ContentXml::writeCell(const QDate & date, const QString & annotation) {

    QDateTime dateTime(date);

    writeCell(dateTime, annotation);

}

void ContentXml::writeCell(bool value, const QString & annotation) {

    writeAutomaticStyles();
    startSpreadsheet();

    if (_tableRowStarted == false) {
        writeLine();
    }
    /*
     * <table:table-cell office:value-type="date"
     * office:date-value="2011-07-16"
     * ><text:p>16/07/11</text:p></table:table-cell>
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-cell");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value-type", "boolean");
    if (_current_style_ref != nullptr) {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", _current_style_ref->_ref_str);
    }
    else {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ce1");
    }

    QString bvalue = "false";
    if (value) {
        bvalue = "true";
    }
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"boolean-value", bvalue);
    writeAnnotation(annotation);
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "p");
    _p_writer->writeCharacters(bvalue);
    _p_writer->writeEndElement();

    /*
     * </table:table-cell>
     */
    _p_writer->writeEndElement();
}

// public void writeCell(Duration duration) throws XMLStreamException {
//     if (duration == null) {
//         this.writeCell("");
//     } else {
//         if (this.tableRowStarted == false) {
//             this.writeLine();
//         }
//         /*
//          * <table:table-cell office:value-type="date"
//          * office:date-value="2011-07-16"
//          * ><text:p>16/07/11</text:p></table:table-cell>
//          */
//         writer.writeStartElement("table", "table-cell",
//         hashNamespaceURI.get("table"));
//         writer.writeAttribute("office", hashNamespaceURI.get("office"),
//         "value-type", "time");
//         writer.writeAttribute("office", hashNamespaceURI.get("office"),
//         "time-value", duration.toString());
//         writer.writeAttribute("table", hashNamespaceURI.get("table"),
//         "style-name", "ce2");
//         /*
//          * <text:p>12:00:00</text:p>
//          */
//         writer.writeStartElement("text", "p", hashNamespaceURI.get("text"));
//         writer.writeCharacters(duration.getHours() + ":"
//         + duration.getMinutes() + ":" + duration.getSeconds());
//         writer.writeEndElement();
//
//         /*
//          * </table:table-cell>
//          */
//         writer.writeEndElement();
//         /*
//          * </table:table-row> </table:table> </office:spreadsheet>
//          * </office:body>
//          */
//     }
// }

void ContentXml::writeCell(const QUrl & theUri, const QString & description, const QString & annotation) {
    // <table:table-cell office:value-type="string"><text:p><text:a
    // xlink:href="http://linuxfr.org/">linuxfr</text:a></text:p></table:table-cell>

    //<table:table-cell office:value-type="string" calcext:value-type="string">
    //<text:p>
    //<text:a xlink:href="http://pappso.inra.fr/" xlink:type="simple">
        //ceci est un lien</text:a></text:p>
    //</table:table-cell>
    writeAutomaticStyles();
    startSpreadsheet();

    if (_tableRowStarted == false) {
        writeLine();
    }
    /*
     * <table:table-cell office:value-type="string">
     */
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("table"), "table-cell");
    
    if (_current_style_ref != nullptr) {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", _current_style_ref->_ref_str);
    }
    else {
        _p_writer->writeAttribute(MetaXml::getNamespaceURI("table"),"style-name", "ce1");
    }

    _p_writer->writeAttribute(MetaXml::getNamespaceURI("office"),"value-type", "string");
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("calcext"),"value-type", "string");

    writeAnnotation(annotation);
    
    _p_writer->setAutoFormatting(false);
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "p");
    _p_writer->writeStartElement(MetaXml::getNamespaceURI("text"), "a");
    // xlink:href="http://linuxfr.org/"
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("xlink"), "href",theUri.toString());
    _p_writer->writeAttribute(MetaXml::getNamespaceURI("xlink"), "type","simple");
    _p_writer->writeCharacters(description);
    _p_writer->writeEndElement();
    _p_writer->writeEndElement();
    
    _p_writer->setAutoFormatting(true);

    _p_writer->writeEndElement();



}

OdsTableCellStyleRef ContentXml::getTableCellStyleRef(const OdsTableCellStyle & style) {
    if (_automatic_styles_writed) {
        throw OdsException(QObject::tr("unable to get style reference : styles already written"));
    }

    _style2write.push_back(style);

    OdsTableCellStyleRef _p_ref = new OdsTableCellStyleRefInternal(_style2write.size());
    _style_ref_list.push_back(_p_ref);
    return _p_ref;
}


void ContentXml::setTableCellStyleRef(OdsTableCellStyleRef style_ref) {
    if (style_ref != nullptr) {
        auto it = find (_style_ref_list.begin(), _style_ref_list.end(), style_ref);
        if (it == _style_ref_list.end()) {
            throw OdsException(QObject::tr("this style reference was not registered in this document"));
        }
    }

    _current_style_ref = style_ref;
}
