/***************************************************************************
 *   Copyright (C) 2005 by Thierry CHARLES   *
 *   thierry@les-charles.net   *
 *                                                                         *
 *   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.             *
 ***************************************************************************/

#include "stylesres.h"

#include <wx/font.h>

#include "lib/lib_logging.h"
#include "xpe_components/editor/editor_styles.h"
#include "xpe_components/editor/editor_panelelement.h"

void StylesRes::applyStyles(TCodeEditor * editor) const
{
    wxFont font = wxFont(this->iFontSize,wxFONTFAMILY_MODERN,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL);
    editor->SetFont(font);

    editor->SetBackgroundColour(this->bgColor.toWxColour());

    TStylesMap::const_iterator it = this->stylesMap.begin();
    TStylesMap::const_iterator itE = this->stylesMap.end();
    while(it != itE)
    {
        editor->setStyle((*it).first,(*it).second);
        it++;
    }


    TSelectionsStyleMap::const_iterator it2 = this->selectionsStyleMap.begin();
    TSelectionsStyleMap::const_iterator it2E = this->selectionsStyleMap.end();
    while(it2 != it2E)
    {
        editor->setSelectionStyle((*it2).second,(*it2).first);
        it2++;
    }

    editor->setSelectionStyle(TCODEEDITOR_DEFAULT_SELECTION,SELECTED_STYLE);
    editor->setSelectionStyle(TCODEEDITOR_OPEN_BRACKET_SELECTION,STYLE_BRACKET);
    editor->setSelectionStyle(TCODEEDITOR_CLOSE_BRACKET_SELECTION,STYLE_BRACKET);

    editor->Refresh(true);
}

void StylesRes::setBgColor(const TColor & color)
{
    this->bgColor = color;
    this->fireRessourceEvent(0);
}

/** defini le style pour un ID donne */
void StylesRes::setStyle(int iStyleID, const TStyle & style)
{
    this->stylesMap[iStyleID] = style;
    this->fireRessourceEvent(1);
}

/**
 * defini le style de la selection
 * @param iSelection id de la selection a manipuler
 * @param iStyle ID du style a appliquer a la sélection (voir setStyle)
 */
void StylesRes::setSelectionStyle(const int iSelection, const int iStyleId)
{
    this->selectionsStyleMap[iSelection] = iStyleId;
    this->fireRessourceEvent(2);
}

/** défini la taille de la police */
void StylesRes::setFontSize(int iFontSize)
{
    this->iFontSize = iFontSize;
    this->fireRessourceEvent(3);
}


/** charge les parametres par défaut */
void StylesRes::loadDefaultParameters()
{
    this->setFontSize(11);
    this->bgColor = TColor(255,255,255);
    TStyle style;
    style.setFgColor(TColor(0,0,0));
    this->setStyle(DEFAULT_STYLE,style);
    style.setFgColor(TColor(0,0,0));
    this->setStyle(STYLE_IDENT,style);
    style.setFgColor(TColor(64,0,128));
    style.setBold( true );
    this->setStyle(STYLE_KEYWORD,style);
    style.setBold( false );
    style.setFgColor(TColor(127,0,0));
    this->setStyle(STYLE_NUMBER,style);
    style.setFgColor(TColor(0,0,195));
    this->setStyle(STYLE_STRING,style);
    style.setFgColor(TColor(0,127,127));
    this->setStyle(STYLE_CHAR,style);
    style.setFgColor(TColor(127,127,127));
    style.setItalic( true );
    this->setStyle(STYLE_COMMENT,style);

    style.setFgColor( TColor(255,255,255) );
    style.setBgColor( TColor(0,77,153) );
    style.setBold(false);
    style.setItalic(false);
    this->setStyle(SELECTED_STYLE,style);

    style.setFgColor( TColor(0,0,0) );
    style.setBgColor( TColor(255,204,153) );
    this->setStyle(STYLE_BRACKET,style);

    this->setSelectionStyle(TCODEEDITOR_DEFAULT_SELECTION,SELECTED_STYLE);
    this->setSelectionStyle(TCODEEDITOR_OPEN_BRACKET_SELECTION,STYLE_BRACKET);
    this->setSelectionStyle(TCODEEDITOR_CLOSE_BRACKET_SELECTION,STYLE_BRACKET);

}


#define XMLCC_NODE_STYLES "Styles"
#define XMLCC_ATTR_FONTSIZE "fontSize"
#define XMLCC_NODE_STYLE "Style"
#define XMLCC_ATTR_STYLE_ID "id"
#define XMLCC_ATTR_STYLE_BOLD "bold"
#define XMLCC_ATTR_STYLE_ITALIC "italic"
#define XMLCC_ATTR_STYLE_UNDERLINED "underlined"
#define XMLCC_NODE_FGCOLOR "FgColor"
#define XMLCC_NODE_BGCOLOR "BgColor"
#define XMLCC_ATTR_COLOR_RED "red"
#define XMLCC_ATTR_COLOR_GREEN "green"
#define XMLCC_ATTR_COLOR_BLUE "blue"

#define XMLCC_NODE_SELSTYLES "SelStyles"
#define XMLCC_NODE_SELSTYLE "SelStyle"
#define XMLCC_ATTR_SELSTYLE_SEL "selection"
#define XMLCC_ATTR_SELSTYLE_STYLE "style"

/**
 * charge les parametres du composant a partir des informations
 * contenues dans le noeud passé en paramètre
 */
bool StylesRes::loadParameters(TiXmlElement * parametersNode)
{
    if(!parametersNode)
        return false;

    bool bOK = true;

    TiXmlElement * stylesRoot = parametersNode->FirstChildElement( XMLCC_NODE_STYLES );
    if(stylesRoot)
    {
        if(stylesRoot->QueryValueAttribute(XMLCC_ATTR_FONTSIZE,&this->iFontSize) != TIXML_SUCCESS)
            bOK = false;

//        this->stylesMap.erase(this->stylesMap.begin(),this->stylesMap.end());

        TiXmlElement * elt = stylesRoot->FirstChildElement( XMLCC_NODE_BGCOLOR );
        if(elt)
        {
            uint iRed, iGreen, iBlue;

            if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_RED,&iRed) != TIXML_SUCCESS)
                bOK = false;

            if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_GREEN,&iGreen) != TIXML_SUCCESS)
                bOK = false;

            if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_BLUE,&iBlue) != TIXML_SUCCESS)
                bOK = false;

            this->bgColor = TColor(iRed,iGreen,iBlue);
        }
        else
            bOK = false;

        TiXmlElement * styleElt = stylesRoot->FirstChildElement( XMLCC_NODE_STYLE );
        while(styleElt)
        {
            TStyle style;

            bool bBold, bItalic, bUnder;
            int iStyleID;

            if(styleElt->QueryIntAttribute(XMLCC_ATTR_STYLE_ID,&iStyleID) != TIXML_SUCCESS)
                bOK = false;

            if(styleElt->QueryValueAttribute(XMLCC_ATTR_STYLE_BOLD,&bBold) != TIXML_SUCCESS)
                bOK = false;

            if(styleElt->QueryValueAttribute(XMLCC_ATTR_STYLE_ITALIC,&bItalic) != TIXML_SUCCESS)
                bOK = false;

            if(styleElt->QueryValueAttribute(XMLCC_ATTR_STYLE_UNDERLINED,&bUnder) != TIXML_SUCCESS)
                bOK = false;

            style.setBold( bBold );
            style.setItalic( bItalic );
            style.setUnderlined( bUnder );

            elt = styleElt->FirstChildElement( XMLCC_NODE_FGCOLOR );
            if(elt)
            {
                uint iRed, iGreen, iBlue;

                if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_RED,&iRed) != TIXML_SUCCESS)
                    bOK = false;

                if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_GREEN,&iGreen) != TIXML_SUCCESS)
                    bOK = false;

                if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_BLUE,&iBlue) != TIXML_SUCCESS)
                    bOK = false;

                style.setFgColor( TColor(iRed,iGreen,iBlue) );
            }
            else
                bOK = false;

            elt = styleElt->FirstChildElement( XMLCC_NODE_BGCOLOR );
            if(elt)
            {
                uint iRed, iGreen, iBlue;

                if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_RED,&iRed) != TIXML_SUCCESS)
                    bOK = false;

                if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_GREEN,&iGreen) != TIXML_SUCCESS)
                    bOK = false;

                if(elt->QueryValueAttribute(XMLCC_ATTR_COLOR_BLUE,&iBlue) != TIXML_SUCCESS)
                    bOK = false;

                style.setBgColor( TColor(iRed,iGreen,iBlue) );
            }
            else
                style.removeBgColor();

            if(bOK)
            {
                this->stylesMap[iStyleID] = style;
            }
            else
            {
                LOG_MESSAGE("Parametres de configuration des styles corrompus.",logging::_INFO_);
            }


            styleElt = styleElt->NextSiblingElement( XMLCC_NODE_STYLE );
        }
    }

    TiXmlElement * selStylesRoot = parametersNode->FirstChildElement( XMLCC_NODE_SELSTYLES );
    if(selStylesRoot)
    {
//        this->selectionsStyleMap.erase(this->selectionsStyleMap.begin(),this->selectionsStyleMap.end());

        TiXmlElement * elt = selStylesRoot->FirstChildElement( XMLCC_NODE_SELSTYLE );
        while(elt)
        {
            int iSel, iStyle;

            if(elt->QueryIntAttribute(XMLCC_ATTR_SELSTYLE_SEL,&iSel) != TIXML_SUCCESS)
                bOK = false;

            if(elt->QueryIntAttribute(XMLCC_ATTR_SELSTYLE_STYLE,&iStyle) != TIXML_SUCCESS)
                bOK = false;

            if(bOK)
            {
                this->setSelectionStyle(iSel,iStyle);
            }
            else
            {
                LOG_MESSAGE("Parametres de configuration des styles des selections corrompus.",logging::_INFO_);
            }

            elt = elt->NextSiblingElement( XMLCC_NODE_SELSTYLE );
        }

    }

    this->fireRessourceEvent(3);
    return bOK;
}

/** renvoie les parametres du composant sous la forme d'un noeud xml */
TiXmlElement * StylesRes::getParameters()
{
    TiXmlElement * parametersNode = new TiXmlElement(XMLCC_NODE_STYLESRES_PARAMETERS);

    TiXmlElement * stylesRoot = new TiXmlElement(XMLCC_NODE_STYLES);
    parametersNode->LinkEndChild( stylesRoot );
    stylesRoot->SetAttribute(XMLCC_ATTR_FONTSIZE,this->iFontSize);

    TiXmlElement * elt = new TiXmlElement( XMLCC_NODE_BGCOLOR );
    stylesRoot->LinkEndChild( elt );
    {
        elt->SetAttribute(XMLCC_ATTR_COLOR_RED,this->bgColor.getRed());
        elt->SetAttribute(XMLCC_ATTR_COLOR_GREEN,this->bgColor.getGreen());
        elt->SetAttribute(XMLCC_ATTR_COLOR_BLUE,this->bgColor.getBlue());
    }

    TStylesMap::const_iterator it = this->stylesMap.begin();
    TStylesMap::const_iterator itE = this->stylesMap.end();
    while(it != itE)
    {
        TiXmlElement * styleElt = new TiXmlElement(XMLCC_NODE_STYLE);
        stylesRoot->LinkEndChild( styleElt );

        const TStyle & style = (*it).second;

        styleElt->SetAttribute(XMLCC_ATTR_STYLE_ID,(*it).first);
        styleElt->SetAttribute(XMLCC_ATTR_STYLE_BOLD,style.isBold());
        styleElt->SetAttribute(XMLCC_ATTR_STYLE_ITALIC,style.isItalic());
        styleElt->SetAttribute(XMLCC_ATTR_STYLE_UNDERLINED,style.isUnderlined());

        elt = new TiXmlElement( XMLCC_NODE_FGCOLOR );
        styleElt->LinkEndChild( elt );
        {
            const TColor & col = style.getFgColor();
            elt->SetAttribute(XMLCC_ATTR_COLOR_RED,col.getRed());
            elt->SetAttribute(XMLCC_ATTR_COLOR_GREEN,col.getGreen());
            elt->SetAttribute(XMLCC_ATTR_COLOR_BLUE,col.getBlue());
        }

        if(style.hasBgColor())
        {
            elt = new TiXmlElement( XMLCC_NODE_BGCOLOR );
            styleElt->LinkEndChild( elt );
            {
                const TColor & col = style.getBgColor();
                elt->SetAttribute(XMLCC_ATTR_COLOR_RED,col.getRed());
                elt->SetAttribute(XMLCC_ATTR_COLOR_GREEN,col.getGreen());
                elt->SetAttribute(XMLCC_ATTR_COLOR_BLUE,col.getBlue());
            }
        }
        it++;
    }

    TiXmlElement * selStylesRoot = new TiXmlElement(XMLCC_NODE_SELSTYLES);
    parametersNode->LinkEndChild( selStylesRoot );

    TSelectionsStyleMap::const_iterator it2 = this->selectionsStyleMap.begin();
    TSelectionsStyleMap::const_iterator it2E = this->selectionsStyleMap.end();
    while(it2 != it2E)
    {
        TiXmlElement * elt = new TiXmlElement( XMLCC_NODE_SELSTYLE );
        selStylesRoot->LinkEndChild( elt );

        elt->SetAttribute(XMLCC_ATTR_SELSTYLE_SEL, (*it2).first);
        elt->SetAttribute(XMLCC_ATTR_SELSTYLE_STYLE, (*it2).second);

        it2++;
    }

    return parametersNode;
}



