/* AbiSource
 * 
 * Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com>
 * Copyright (C) 2004 Robert Staudinger <robsta@stereolyzer.net>
 * Copyright (C) 2005 Daniel d'Andrada T. de Carvalho
 * <daniel.carvalho@indt.org.br>
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  
 * 02111-1307, USA.
 */

 
// Class definition include
#include "OO_StylesWriter.h"
 
// Internal includes
#include "OO_StylesContainer.h"
#include "OO_Common.h"
 
// Abiword includes
#include <ut_string_class.h>
#include <pd_Style.h>
#include <pd_Document.h>
#include <pp_AttrProp.h>
#include <ut_math.h>
 
// External includes
#include <gsf/gsf-output-stdio.h>
#include <gsf/gsf-outfile.h>
 
 
/**
 * 
 */
bool OO_StylesWriter::writeStyles(PD_Document * pDoc, GsfOutfile * oo, OO_StylesContainer & stylesContainer)
{
    GsfOutput* styleStream = gsf_outfile_new_child (oo, "styles.xml", FALSE);
  
    static const char * const preamble [] = 
    {      
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
        "<!DOCTYPE office:document-styles PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"office.dtd\">\n",
        "<office:document-styles xmlns:office=\"http://openoffice.org/2000/office\" xmlns:style=\"http://openoffice.org/2000/style\" xmlns:text=\"http://openoffice.org/2000/text\" xmlns:table=\"http://openoffice.org/2000/table\" xmlns:draw=\"http://openoffice.org/2000/drawing\" xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:number=\"http://openoffice.org/2000/datastyle\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:chart=\"http://openoffice.org/2000/chart\" xmlns:dr3d=\"http://openoffice.org/2000/dr3d\" xmlns:math=\"http://www.w3.org/1998/Math/MathML\" xmlns:form=\"http://openoffice.org/2000/form\" xmlns:script=\"http://openoffice.org/2000/script\" office:version=\"1.0\">\n"
    };
  
    static const char * const midsection [] = 
    {      
        "<office:styles>\n",
        "<style:default-style style:family=\"graphics\">\n",
        "<style:properties draw:start-line-spacing-horizontal=\"0.283cm\" draw:start-line-spacing-vertical=\"0.283cm\" draw:end-line-spacing-horizontal=\"0.283cm\" draw:end-line-spacing-vertical=\"0.283cm\" fo:color=\"#000000\" style:font-name=\"Nimbus Roman No9 L\" fo:font-size=\"12pt\" fo:language=\"en\" fo:country=\"US\" style:font-name-asian=\"HG Mincho Light J\" style:font-size-asian=\"12pt\" style:language-asian=\"none\" style:country-asian=\"none\" style:font-name-complex=\"Arial Unicode MS\" style:font-size-complex=\"12pt\" style:language-complex=\"none\" style:country-complex=\"none\" style:text-autospace=\"ideograph-alpha\" style:punctuation-wrap=\"simple\" style:line-break=\"strict\">\n",
        "<style:tab-stops/>\n",
        "</style:properties>\n",
        "</style:default-style>\n",
        "<style:default-style style:family=\"paragraph\">\n",
        "<style:properties fo:color=\"#000000\" style:font-name=\"Nimbus Roman No9 L\" fo:font-size=\"12pt\" fo:language=\"en\" fo:country=\"US\" style:font-name-asian=\"HG Mincho Light J\" style:font-size-asian=\"12pt\" style:language-asian=\"none\" style:country-asian=\"none\" style:font-name-complex=\"Arial Unicode MS\" style:font-size-complex=\"12pt\" style:language-complex=\"none\" style:country-complex=\"none\" fo:hyphenate=\"false\" fo:hyphenation-remain-char-count=\"2\" fo:hyphenation-push-char-count=\"2\" fo:hyphenation-ladder-count=\"no-limit\" style:text-autospace=\"ideograph-alpha\" style:punctuation-wrap=\"hanging\" style:line-break=\"strict\" style:tab-stop-distance=\"2.205cm\"/>\n",
        "</style:default-style>\n"
    };
  
    UT_UTF8String styles;
    const PD_Style * pStyle = NULL;
    UT_GenericVector<PD_Style *> vecStyles;
    pDoc->getAllUsedStyles(&vecStyles);
    UT_uint32 k = 0;
    UT_UTF8String styleAtts, propAtts, font;
    
    for (k=0; k < vecStyles.getItemCount(); k++)
    {
        pStyle = vecStyles.getNthItem(k);
        PT_AttrPropIndex api = pStyle->getIndexAP();
        const PP_AttrProp * pAP = NULL;
        bool bHaveProp = pDoc->getAttrProp (api, &pAP);
      
        if (bHaveProp && pAP) 
        {
            OO_StylesWriter::map(pAP, styleAtts, propAtts, font);
      
            styles += "<style:style " + styleAtts + ">\n";
            styles += "<style:properties " + propAtts + "/>\n";
            styles += "</style:style>\n";
        }
      
        if (font.size())
        {
            UT_String f = font.utf8_str();
            stylesContainer.addFont(f);
            font.clear();
        }
    }
  
    static const char * const postamble [] = 
    {
        "<text:outline-style>\n",
        "<text:outline-level-style text:level=\"1\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"2\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"3\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"4\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"5\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"6\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"7\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"8\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"9\" style:num-format=\"\"/>\n",
        "<text:outline-level-style text:level=\"10\" style:num-format=\"\"/>\n",
        "</text:outline-style>\n",
        "<text:footnotes-configuration style:num-format=\"1\" text:start-value=\"0\" text:footnotes-position=\"page\" text:start-numbering-at=\"document\"/>\n",
        "<text:endnotes-configuration style:num-format=\"i\" text:start-value=\"0\"/>\n",
        "<text:linenumbering-configuration text:number-lines=\"false\" text:offset=\"0.499cm\" style:num-format=\"1\" text:number-position=\"left\" text:increment=\"5\"/>\n",
        "</office:styles>\n",
        "<office:automatic-styles>\n",
        "<style:page-master style:name=\"pm1\">\n",
        "<style:properties fo:page-width=\"21.59cm\" fo:page-height=\"27.94cm\" style:num-format=\"1\" style:print-orientation=\"portrait\" fo:margin-top=\"2.54cm\" fo:margin-bottom=\"2.54cm\" fo:margin-left=\"3.175cm\" fo:margin-right=\"3.175cm\" style:footnote-max-height=\"0cm\">\n",
        "<style:footnote-sep style:width=\"0.018cm\" style:distance-before-sep=\"0.101cm\" style:distance-after-sep=\"0.101cm\" style:adjustment=\"left\" style:rel-width=\"25%\" style:color=\"#000000\"/>\n",
        "</style:properties>\n",
        "<style:header-style/>\n",
        "<style:footer-style/>\n",
        "</style:page-master>\n",
        "</office:automatic-styles>\n",
        "<office:master-styles>\n",
        "<style:master-page style:name=\"Standard\" style:page-master-name=\"pm1\"/>\n",
        "</office:master-styles>\n",
        "</office:document-styles>\n"
    };
  
    oo_writeToStream(styleStream, preamble, NrElements(preamble));
      
    UT_UTF8String fontDecls = "<office:font-decls>\n";
    OO_StylesWriter::addFontDecls(fontDecls, stylesContainer);
    fontDecls += "</office:font-decls>\n";
    oo_writeUTF8String(styleStream, fontDecls.utf8_str());
      
    oo_writeToStream(styleStream, midsection, NrElements(midsection));
    oo_writeUTF8String(styleStream, styles.utf8_str());
    oo_writeToStream(styleStream, postamble, NrElements(postamble));
      
    oo_gsf_output_close(styleStream);
      
    return true;
}


/**
 * 
 */
void OO_StylesWriter::addFontDecls(UT_UTF8String & buffer, OO_StylesContainer & stylesContainer)
{
    UT_GenericVector<const UT_String*> *vecFonts = stylesContainer.getFontsKeys();
    for (int i = 0; i < vecFonts->size(); i++) {
        // FIXME ATM only variable width fonts
        // check here by using pango?
        const XML_Char * pitch = "variable";
        const UT_String * font = vecFonts->getNthItem(i);
        buffer += UT_UTF8String_sprintf("<style:font-decl style:name=\"%s\" fo:font-family=\"'%s'\" style:font-pitch=\"%s\"/>\n", 
                        font->c_str(), font->c_str(), pitch);
    }
    DELETEP(vecFonts);
}


/**
 * 
 */
void OO_StylesWriter::map(const PP_AttrProp * pAP, UT_UTF8String & styleAtts, UT_UTF8String & propAtts, UT_UTF8String & font) 
{       
    const XML_Char * szValue = NULL;
    styleAtts.clear();
    propAtts.clear();

    // Attributes
    if (pAP->getAttribute("name", szValue)) 
        styleAtts += UT_UTF8String_sprintf("style:name=\"%s\" ", szValue);

    if (pAP->getAttribute("type", szValue)) 
        if (!UT_strcmp(szValue, "P"))
        {
            styleAtts += UT_UTF8String_sprintf("style:family=\"paragraph\" ");
            styleAtts += UT_UTF8String_sprintf("style:class=\"text\" ");
        }

    if (pAP->getAttribute("basedon", szValue)) 
        styleAtts += UT_UTF8String_sprintf("style:parent-style-name=\"%s\" ", szValue);
    
    if (pAP->getAttribute("followedby", szValue)) 
    {
        // ignore, current style is default
        if (UT_strcmp(szValue, "Current Settings"))
            styleAtts += UT_UTF8String_sprintf("style:next-style-name=\"%s\" ", szValue);
    }

    // Properties
    // please keep alphabetic order
    if (pAP->getProperty("bgcolor", szValue)) 
    {
        propAtts += UT_UTF8String_sprintf("style:text-background-color=\"#%s\" ", szValue); // # is eaten unless escaped
    }

    if (pAP->getProperty("color", szValue)) 
    {
        propAtts += UT_UTF8String_sprintf("fo:color=\"#%s\" ", szValue); // # is eaten unless escaped
    }

    if (pAP->getProperty("dom-dir", szValue)) //:ltr; 
        if (!UT_strcmp(szValue, "rtl"))
        {
            // FIXME some of these parameters are mentioned more than once
            propAtts += UT_UTF8String_sprintf("fo:text-align", "end");
            propAtts += UT_UTF8String_sprintf("style:justify-single-word", "false");
            propAtts += UT_UTF8String_sprintf("style:writing-mode", "rl-tb");
        }

    if (pAP->getProperty("font-family", szValue)) 
    {
        propAtts += UT_UTF8String_sprintf("style:font-name=\"%s\" ", szValue);
        propAtts += UT_UTF8String_sprintf("style:font-name-asian=\"%s\" ", szValue);
        propAtts += UT_UTF8String_sprintf("style:font-name-complex=\"%s\" ", szValue);

        // store font for font-decls
        font = szValue;
    }

    if (pAP->getProperty("font-size", szValue)) 
    {
        propAtts += UT_UTF8String_sprintf("fo:font-size=\"%gpt\" ", UT_convertToPoints(szValue));
        propAtts += UT_UTF8String_sprintf("style:font-size-asian=\"%gpt\" ", UT_convertToPoints(szValue));
        propAtts += UT_UTF8String_sprintf("style:font-size-complex=\"%gpt\" ", UT_convertToPoints(szValue));
    }

    if (pAP->getProperty("font-stretch", szValue)) 
    {
        /*TODO*/
        // is this "fo:letter-spacing" ?
    }

    if (pAP->getProperty("font-style", szValue)) 
    {
        // fo: style: style: according to spec
        propAtts += UT_UTF8String_sprintf("fo:font-style=\"%s\" ", szValue);
        propAtts += UT_UTF8String_sprintf("style:font-style-asian=\"%s\" ", szValue);
        propAtts += UT_UTF8String_sprintf("style:font-style-complex=\"%s\" ", szValue);
    }

    if (pAP->getProperty("font-variant", szValue)) 
        propAtts += UT_UTF8String_sprintf("fo:font-variant=\"%s\" ", szValue);

    if (pAP->getProperty("font-weight", szValue)) 
    {
        propAtts += UT_UTF8String_sprintf("fo:font-weight=\"%s\" ", szValue);
        propAtts += UT_UTF8String_sprintf("style:font-weight-asian=\"%s\" ", szValue);
        propAtts += UT_UTF8String_sprintf("style:font-weight-complex=\"%s\" ", szValue);
    }

    if (pAP->getProperty("keep-with-next", szValue)) 
    {/*TODO*/}

    if (pAP->getProperty("line-height", szValue))
    {
        if (szValue[strlen(szValue)] == '+')
            propAtts += UT_UTF8String_sprintf("style:line-height-at-least=\"%fcm\" ", UT_convertToDimension(szValue, DIM_CM));
        else if (UT_determineDimension(szValue, DIM_none) == DIM_none)
            propAtts += UT_UTF8String_sprintf("fo:line-height=\"%d%%\" ", rint(atof(szValue) * 100));
        else
            propAtts += UT_UTF8String_sprintf("fo:line-height=\"%fcm\" ", UT_convertToDimension(szValue, DIM_CM));
            // propAtts += UT_UTF8String_sprintf("fo:style:line-spacing=\"%d\%\" ", rint(atof(szValue) * 100));
    }

    if (pAP->getProperty("margin-left", szValue))
        propAtts += UT_UTF8String_sprintf("fo:margin-left=\"%s\" ", szValue);           

    if (pAP->getProperty("margin-top", szValue))
        propAtts += UT_UTF8String_sprintf("fo:margin-top=\"%s\" ", szValue);            

    if (pAP->getProperty("margin-right", szValue))
        propAtts += UT_UTF8String_sprintf("fo:margin-right=\"%s\" ", szValue);          

    if (pAP->getProperty("margin-bottom", szValue))
        propAtts += UT_UTF8String_sprintf("fo:margin-bottom=\"%s\" ", szValue);         

    if (pAP->getProperty("text-align", szValue)) //left center right -> start end left right center justify
    {
        if (UT_strcmp(szValue, "left")) // skip default
        {
            propAtts += UT_UTF8String_sprintf("style:justify-single-word=\"false\" ");

            if (!UT_strcmp(szValue, "right"))
                propAtts += UT_UTF8String_sprintf("fo:text-align=\"end\" ");
            else
                propAtts += UT_UTF8String_sprintf("fo:text-align=\"%s\" ", szValue);
        }
    }

    if (pAP->getProperty("text-decoration", szValue))
    {
        if (strstr(szValue, "underline"))
        {
            propAtts += "style:text-underline=\"single\" ";
            propAtts += "style:text-underline-color=\"font-color\" ";
        }

        if (strstr(szValue, "line-through"))
            propAtts += "style:text-crossing-out=\"single-line\" ";
    }

    if (pAP->getProperty("text-indent", szValue))
    {
        propAtts += UT_UTF8String_sprintf("fo:text-indent=\"%s\" ", szValue);
        propAtts += UT_UTF8String_sprintf("style:auto-text-indent=\"false\" ");
    }

    if (pAP->getProperty("text-position", szValue))
    {
        if (!UT_strcmp(szValue, "superscript"))
            propAtts += "style:text-position=\"super 58%\" ";
        else if (!UT_strcmp(szValue, "subscript"))
            propAtts += "style:text-position=\"sub 58%\" ";
    }

    if (pAP->getProperty("widows", szValue))
    {/*TODO*/}
}
 