/***************************************************************************
 *   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 "pov_panelelement.h"
#include "pov_enlighter.h"
#include "keywordsres.h"
#include "xpe_components/res_id.h"
#include "xpe_components/parser/povparserres.h"
#include "xpe_components/parser/fileinfo.h"
#include "xpe_components/parser/povfileinfo.h"
#include "components/codeeditor/tcodeeditor.h"
#include "components/framework/tapplicationpanel.h"
#include "components/framework/tapplication.h"
#include "components/framework/tmainwindow.h"
#include "components/stdgui/tpanel.h"
#include "components/stdgui/tbitmap.h"

#include "bmp_id.h"

#include "lib/lib_logging.h"

PovPanelElement::PovPanelElement(TApplicationPanel * _owner, int iID)
    : EditorPanelElement(_owner, iID)
{
    this->setName(wxTr("New Povray File"));
    this->setBitmaps(GET_BMP(BMP_FILE_POVRAY_ID),GET_BMP(BMP_FILE_POVRAY_M_ID));
}

PovPanelElement::~PovPanelElement()
{
}

/** construit le panneau conteneur et son contenu (appelle automatiquement par getContentPanel et detruit automatiquement par le destructeur) */
TPanel * PovPanelElement::buildContentPanel()
{
    TPanel * panel = EditorPanelElement::buildContentPanel( false );
    TCodeEditor * editor = this->getEditor();

    KeywordsListRes * keywords = static_cast<KeywordsListRes *>(CurrentApplication()->getRessource(POV_KEYWORDS_LIST_RESSOURCE_ID));
    TStringList * keywordsList = NULL;
    if(keywords)
        keywordsList = keywords->getKeywordsList();
    editor->setEnlighter(new PovEnlighter(editor,keywordsList));

    this->setKeywordsListRes( keywords );

    return panel;
}

/** commente la ligne ou se trouve le curseur ou la sélection */
void PovPanelElement::commentIn()
{
    TPoint ptSelStart, ptSelEnd;
    this->getEditor()->getSelection( ptSelStart, ptSelEnd );
    if(ptSelStart.isValid() && ptSelEnd.isValid())
    {
        this->getEditor()->getDocument()->startComposedAction();
        for(int i = ptSelStart.y ; i <= ptSelEnd.y ; i++)
            this->getEditor()->getDocument()->insertAt( wxT("//"), i, 0);
        this->getEditor()->getDocument()->stopComposedAction();
        this->getEditor()->setSelection( ptSelStart, ptSelEnd );
    }
    else
    {
        int iLine = this->getEditor()->getCursor()->getLine();
        this->getEditor()->getDocument()->insertAt( wxT("//"), iLine, 0);
    }
}

/** dé-commente la ligne ou se trouve le curseur ou la sélection */
void PovPanelElement::commentOut()
{
    TPoint ptSelStart, ptSelEnd;
    this->getEditor()->getSelection( ptSelStart, ptSelEnd );
    if(ptSelStart.isValid() && ptSelEnd.isValid())
    {
        this->getEditor()->getDocument()->startComposedAction();
        for(int i = ptSelStart.y ; i <= ptSelEnd.y ; i++)
        {
            const wxString & s = this->getEditor()->getDocument()->getLine( i );
            uint j;
            for(j = 0 ; j < s.length() ; j++)
            {
                if(!isspace(s[j]))
                    break;
            }
            if( j < (s.length() - 2))
            {
                if(s[j] == '/' && s[j+1] == '/')
                    this->getEditor()->getDocument()->removeRange( TPoint(j,i), TPoint(j+2,i) );
            }
        }
        this->getEditor()->getDocument()->stopComposedAction();
        this->getEditor()->setSelection( ptSelStart, ptSelEnd );
    }
    else
    {
        int iLine = this->getEditor()->getCursor()->getLine();
        const wxString & s = this->getEditor()->getDocument()->getLine( iLine );
        uint j;
        for(j = 0 ; j < s.length() ; j++)
        {
            if(!isspace(s[j]))
                break;
        }
        if( j < (s.length() - 2))
        {
            if(s[j] == '/' && s[j+1] == '/')
                this->getEditor()->getDocument()->removeRange( TPoint(j,iLine), TPoint(j+2,iLine) );
        }
    }
}

/** charge un fichier apres avoir vidangé le contenu du composant */
bool PovPanelElement::loadFileImpl(const wxString & sFile)
{
    bool bRes = EditorPanelElement::loadFileImpl( sFile );

    if(bRes)
    {
        PovFileParserRes * res = dynamic_cast<PovFileParserRes *>(CurrentApplication()->getRessource( POV_FILES_PARSER_RESSOURCE_ID ));
        if(res)
        {
            FileInfoLocker fileLock(res,this->getID());
            fileLock.getInfo()->readFromCache();
        }
    }

    return bRes;
}

/**
 * renvoie la liste des completions correspondant à un mot
 * @param sWordStart debut du mot a completer
 */
TStringList PovPanelElement::getCompletionsForWord(TCodeEditor * ce, const wxString & sWordStart)
{
    TStringList completions = EditorPanelElement::getCompletionsForWord(ce,sWordStart);

    PovFileParserRes * res = dynamic_cast<PovFileParserRes *>(CurrentApplication()->getRessource( POV_FILES_PARSER_RESSOURCE_ID ));
    if(res)
    {
        TStringSet otherCompletions;

        TStringSet deps = res->getFullDependanciesList(this->getID());

        PovFileInfo * info = NULL;
        TStringSet::iterator it = deps.begin();
        while(it != deps.end())
        {
            FileInfoLocker locker(res,(*it));
            info = dynamic_cast<PovFileInfo *>(locker.getInfo());
            if(info)
            {
                this->fillCompletionsWith(otherCompletions,info,sWordStart,true);
            }
            it++;
        }

        FileInfoLocker locker(res,this->getID());
        info = dynamic_cast<PovFileInfo *>(locker.getInfo());
        if(info)
        {
            this->fillCompletionsWith(otherCompletions,info,sWordStart,false);
        }

        completions.insert(completions.end(),otherCompletions.begin(),otherCompletions.end());
    }

    return completions;
}

void PovPanelElement::fillCompletionsWith(TStringSet & completions, PovFileInfo * info, const wxString & sWordStart, bool bIsInclude)
{
    TNamedPovFileEltMap elts = info->getDistinctElements();
    TNamedPovFileEltMap::iterator it = elts.begin();
    while(it != elts.end())
    {
        bool bInsertable = false;
        if((!bIsInclude) && (*it).second->getType() == PovFileElt::Local)
            bInsertable = true;
        else if((*it).second->getType() == PovFileElt::Declare)
            bInsertable = true;
        else if((*it).second->getType() == PovFileElt::Macro)
            bInsertable = true;

        if(bInsertable)
        {
            if((*it).first.StartsWith(sWordStart))
                completions.insert((*it).first);
        }

        it++;
    }
}


