/* AbiSource Program Utilities
 * 
 * Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com>
 * 
 * Copyright (C) 2005 INdT
 * Author: 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 "ODi_Style_PageLayout.h"

// Internal includes
#include "ODi_ListenerStateAction.h"
#include "ODi_ElementStack.h"

// AbiWord includes
#include <ut_math.h>
#include <fp_PageSize.h>
#include <pd_Document.h>
#include <ut_locale.h>

/**
 * 
 */
void ODi_Style_PageLayout::startElement(const XML_Char* pName,
                                       const XML_Char** ppAtts,
                                       ODi_ListenerStateAction& rAction) {

    const XML_Char* pVal;
                                        
    if (!UT_strcmp("style:page-layout", pName)) {
        
        pVal = UT_getAttribute ("style:name", ppAtts);
        UT_ASSERT(pVal);
        m_name = pVal;
        
    } else if (!UT_strcmp("style:page-layout-properties", pName)) {
        
        _parsePageLayoutProperties(ppAtts);
        
    } else if (!UT_strcmp("style:columns", pName)) {
        
        pVal = UT_getAttribute ("fo:column-count", ppAtts);
        if (pVal) {
            if (!UT_strcmp(pVal,"0")) {  // see Bug 10076
                pVal = "1";
            }
            m_columnCount = pVal;
        }
        
        pVal = UT_getAttribute ("fo:column-gap", ppAtts);
        if (pVal) {
            m_columnGap = pVal;
        }
        
    } else if (!UT_strcmp("style:header-footer-properties", pName)) {
        _parseHeaderFooterProperties(ppAtts);
    }
}


/**
 * 
 */
void ODi_Style_PageLayout::endElement(const XML_Char* pName,
                                     ODi_ListenerStateAction& rAction) {
                                        
    if (!UT_strcmp("style:page-layout", pName)) {
        _buildSectionPropsString();
        rAction.popState();
    }
}


/**
 * Sets the <pagesize> tag.
 */
void ODi_Style_PageLayout::definePageSizeTag(PD_Document* pDocument) const {
    
    UT_uint32 propCtr = 0;
    static const int MAX_PAGE_ATTS = 13; // 2*(width height orientation pagetype units page-scale) 0 
    const XML_Char* pageAtts[MAX_PAGE_ATTS];
    double pageWidthMmNumeric;
    double pageHeightMmNumeric;
    UT_UTF8String pageWidthMm;
    UT_UTF8String pageHeightMm;
    UT_LocaleTransactor lt(LC_NUMERIC, "C");
    
    // width and height are rounded to full mm because that's how they are
    // predefined in Abi and there seem to be rounding errors in oow's exporter

    if (!m_pageWidth.empty()) {
        pageAtts[propCtr++] = "width";
        
        pageWidthMmNumeric = rint(UT_convertToDimension(m_pageWidth.utf8_str(),
                                                        DIM_MM));
        UT_UTF8String_sprintf(pageWidthMm, "%f", pageWidthMmNumeric);
        pageAtts[propCtr++] = pageWidthMm.utf8_str();
    }

    if (!m_pageHeight.empty()) {
        pageAtts[propCtr++] = "height";
        
        pageHeightMmNumeric = rint(UT_convertToDimension(m_pageHeight.utf8_str(),
                                                         DIM_MM));
        UT_UTF8String_sprintf(pageHeightMm, "%f", pageHeightMmNumeric);
        pageAtts[propCtr++] = pageHeightMm.utf8_str();
    }

    pageAtts[propCtr++] = "units";
    pageAtts[propCtr++] = "mm";

    if (!m_printOrientation.empty()) {
        pageAtts[propCtr++] = "orientation";
        pageAtts[propCtr++] = m_printOrientation.utf8_str();
    }

    pageAtts[propCtr++] = "page-scale";
    pageAtts[propCtr++] = "1.0";

    fp_PageSize ps(pageWidthMmNumeric, pageHeightMmNumeric, DIM_MM);
    pageAtts[propCtr++] = "pagetype";
    pageAtts[propCtr++] = ps.getPredefinedName();

    pageAtts[propCtr] = 0; // To signal the end of the array
    
    
    pDocument->setPageSizeFromFile(pageAtts);
}


/**
 * Parses <style:header-footer-properties> start tags.
 */
void ODi_Style_PageLayout::_parseHeaderFooterProperties(const XML_Char** ppAtts) {
    
    const XML_Char* pVal = NULL;
    pVal = UT_getAttribute ("svg:height", ppAtts);
    
    if (m_rElementStack.hasElement("style:header-style")) {
        m_headerHeight = pVal;
        
        pVal = UT_getAttribute ("fo:margin-bottom", ppAtts);
        if (pVal) {
            m_headerMarginBottom = pVal;
        }
    } else {
        UT_ASSERT(m_rElementStack.hasElement("style:footer-style"));
        m_footerHeight = pVal;
        
        pVal = UT_getAttribute ("fo:margin-top", ppAtts);
        if (pVal) {
            m_footerMarginTop = pVal;
        }
    }
}


/**
 * Parses the <style:page-layout-properties> start tag.
 */
void ODi_Style_PageLayout::_parsePageLayoutProperties(const XML_Char** ppAtts) {
    
    const XML_Char* pVal = NULL;
    
    pVal = UT_getAttribute ("fo:page-width", ppAtts);
    if (pVal) {
        m_pageWidth = pVal;
    }

    pVal = UT_getAttribute ("fo:page-height", ppAtts);
    if (pVal) {
        m_pageHeight = pVal;
    }

    pVal = UT_getAttribute ("style:print-orientation", ppAtts);
    if (pVal) {
        m_printOrientation = pVal;
    }

    pVal = UT_getAttribute ("fo:margin-left", ppAtts);
    if (pVal) {
        m_marginLeft = pVal;
    }

    pVal = UT_getAttribute ("fo:margin-top", ppAtts);
    if (pVal) {
        m_marginTop = pVal;
    }

    pVal = UT_getAttribute ("fo:margin-right", ppAtts);
    if (pVal) {
        m_marginRight = pVal;
    }

    pVal = UT_getAttribute ("fo:margin-bottom", ppAtts);
    if (pVal) {
        m_marginBottom = pVal;
    }
}


/**
 * 
 */
void ODi_Style_PageLayout::_buildSectionPropsString() {
    double val;
    UT_UTF8String str;
    UT_LocaleTransactor lt(LC_NUMERIC, "C");
    
    m_sectionProps.clear();
        
        
#define APPEND_STYLE(abiStyName, styValue) \
    if (styValue.size()) { \
        if(m_sectionProps.size()) { \
            m_sectionProps += "; "; \
        } \
        m_sectionProps += abiStyName; \
        m_sectionProps += ":"; \
        m_sectionProps += styValue; \
    }

    APPEND_STYLE("page-margin-left", m_marginLeft);
    APPEND_STYLE("page-margin-right", m_marginRight);
    
    if (m_headerHeight.empty()) {
        // We don't have a header.
        // The property maps directly.
        APPEND_STYLE("page-margin-top", m_marginTop);
    } else {
        // We do have a header.
        // Abi's page-margin-top = OD's page fo:margin-top +
        //                         OD's header svg:height +
        //                         OD's header fo:margim-bottom

        val = UT_convertToDimension(m_marginTop.utf8_str(), DIM_CM);
        
        val += UT_convertToDimension(m_headerHeight.utf8_str(), DIM_CM);
        
        if (!m_headerMarginBottom.empty()) {
            val += UT_convertToDimension(m_headerMarginBottom.utf8_str(), DIM_CM);
        }
        
        UT_UTF8String_sprintf(str, "%fcm", val);
        APPEND_STYLE("page-margin-top", str);
        APPEND_STYLE("page-margin-header", m_marginTop);
    }
    
    if (m_footerHeight.empty()) {
        // We don't have a footer.
        // The property maps directly.
        APPEND_STYLE("page-margin-bottom", m_marginTop);
    } else {
        // We do have a footer.
        // Abi's page-margin-bottom = OD's page fo:margin-bottom +
        //                            OD's footer svg:height +
        //                            OD's footer fo:margim-top

        val = UT_convertToDimension(m_marginBottom.utf8_str(), DIM_CM);
        
        val += UT_convertToDimension(m_footerHeight.utf8_str(), DIM_CM);
        
        if (!m_footerMarginTop.empty()) {
            val += UT_convertToDimension(m_footerMarginTop.utf8_str(), DIM_CM);
        }
        
        UT_UTF8String_sprintf(str, "%fcm", val);
        APPEND_STYLE("page-margin-bottom", str);
        APPEND_STYLE("page-margin-footer", m_marginBottom);
    }
    
    APPEND_STYLE("columns", m_columnCount);
    APPEND_STYLE("column-gap", m_columnGap);
#undef APPEND_STYLE

}
