/* ****************************************************************************
  This file is part of KBabel

  Copyright (C) 2001 by Matthias Kiefer <matthias.kiefer@gmx.de>
		2002 by Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>
                    
  based on code of Andrea Rizzi <rizzi@kde.org>

  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., 675 Mass Ave, Cambridge, MA 02139, USA.

**************************************************************************** */
#include "catalogsettings.h"
#include "tagextractor.h"

#include <kdebug.h>
#include <kstaticdeleter.h>
#include <qregexp.h>

TagListEntry::TagListEntry()
{
    isReg=false;
}

TagListEntry::TagListEntry(QString t,bool is)
    : tag(t)
    , reg(t,false)
    , isReg(is)
{
}

QString TagListEntry::firstMatch(const QString st) const
{
    if(isReg)
    {
        int index=reg.search(st);
        int len=reg.matchedLength();
        if(index < 0)
        {
            return QString::null;
        }
        else
        {
            return st.mid(index,len);
        }
    }
    else 
    {
        int index=st.find(tag);
        if(index >= 0)
        {
            return tag;
        }
    }

    return QString::null;
}

bool TagListEntry::operator==(const TagListEntry & t2)
{
    if(isReg!=t2.isReg) 
        return false;
    
    if(tag!=t2.tag) 
        return false;

    return true;
}
    

TagExtractor::TagExtractor(QString string)
{
    _string=string;
    _tags.setAutoDelete(true);

    processString();  
}

void TagExtractor::setString(QString string)
{
    _string=string;
    processString();
}

uint TagExtractor::countTags()
{
    return _tags.count();
}

QString TagExtractor::firstTag()
{
    TagInfo *ti = _tags.first();

    if(ti)
        return ti->tag;

    return QString::null;
}

QString TagExtractor::nextTag()
{
    TagInfo *ti=_tags.next();
    if(!ti)
        ti=_tags.first();
    
    if(ti)
        return ti->tag;

    return QString::null;
}

QString TagExtractor::tag(uint tagnumber)
{
    TagInfo *ti=_tags.at(tagnumber);
    if(ti)
        return ti->tag;

    return QString::null;
}

QString TagExtractor::prevTag()
{
    TagInfo *ti=_tags.prev();
    if(ti)
        return ti->tag;
    
    return QString::null;
}

QString TagExtractor::lastTag()
{
    TagInfo *ti=_tags.last();
    if(ti)
        return ti->tag;
    
    return QString::null;
} 

QStringList TagExtractor::tags()
{
    QStringList list;
    TagInfo *ti;
    for(ti=_tags.first(); ti!=0; ti = _tags.next())
    {
        list.append(ti->tag);
    }

    return list;
}

QString TagExtractor::plainString(bool keepPos)
{
    QString tmp=_string;

    TagInfo *ti;
    for(ti=_tags.first(); ti != 0; ti=_tags.next())
    {
        uint len=ti->tag.length();
        QString s;
        for(uint i=0; i<len; i++)
        {
             s+=' ';
        }
        tmp.replace(ti->index,len,s);
        
    }
    if(!keepPos)
    {
        tmp=tmp.simplifyWhiteSpace();
    }

    return tmp;
}

QString TagExtractor::tagsReplaced(const QString& replace)
{    
    QString tmp=_string;

    int posCorrection=0;
    int replaceLen=replace.length();

    TagInfo *ti;
    for(ti=_tags.first(); ti != 0; ti=_tags.next())
    {
        uint len=ti->tag.length();
        tmp.replace(ti->index + posCorrection,len,replace);
        
        posCorrection+=(replaceLen-len);
    }

    return tmp;
}


void TagExtractor::addTagIdentifier(QString tag,bool isRegExp)
{
    tagList()->append(TagListEntry(tag,isRegExp));
}

void TagExtractor::deleteTagIdentifier(QString tag,bool isRegExp)
{
    tagList()->remove(TagListEntry(tag,isRegExp));
}
 

void TagExtractor::processString()
{
    _tags.clear();

    QValueList<TagInfo> tmpList;
    
    bool found=false;
    QString tmp=_string;
    do
    {
        found=false;
        QValueList<TagListEntry>::Iterator it;    
        for(it=tagList()->begin();it!=tagList()->end();++it)
        {
            int pos=-1;
            QString tag;
            if( (*it).isRegExp() )
            {
		QRegExp reg = (*it).asRegExp();
		pos = reg.search(tmp);
                int len=reg.matchedLength();
                if(pos>=0)
                {
                    tag=tmp.mid(pos,len);
                }
            }
            else
            {
                pos=tmp.find((*it).asString());
                if(pos>=0)
                {
                    tag=(*it).asString();
                }
            }

            if(pos >= 0)
            {
                found=true;
                
                TagInfo ti;
                ti.index=pos;
                ti.tag=tag;
                tmpList.append(ti);

                QString s;
                for(uint i=0; i<tag.length(); i++)
                {
                    s+=' ';
                }
                tmp.replace(pos,tag.length(),s);

                break;
            }
        }
    }
    while( found );

    uint num=tmpList.count();
    
    for(uint i=0; i < num; i++)
    {
        uint n= 0;
        uint min=_string.length();
        uint counter=0;
        QValueList<TagInfo>::Iterator it;    
        for(it=tmpList.begin();it!=tmpList.end();++it)
        {
            if((*it).index < min)
            {
                min=(*it).index;
                n=counter;
            }
            
            counter++;
        }

        it=tmpList.at(n);
        TagInfo *ti = new TagInfo;
        ti->index=(*it).index;
        ti->tag=(*it).tag;
        _tags.append(ti);
        tmpList.remove(it);
    }

}

QValueList<TagListEntry> *TagExtractor::_tagList=0;
KStaticDeleter< QValueList<TagListEntry> > sdTL;

QValueList<TagListEntry> *TagExtractor::tagList()
{
    if(!_tagList)
    {
	QStringList s = Defaults::Tag::expressions();
	setTagExpressions( &s );
//        _tagList = sdTL.setObject( new QValueList<TagListEntry> );
        //Build the default tag list
//        _tagList->append(TagListEntry("</[A-Za-z0-9\\n]+>",true));
///        _tagList->append(TagListEntry("<[A-Za-z0-9\\n]+[^>]*/?>",true));  
//        _tagList->append(TagListEntry("http:\\/\\/[a-zA-Z0-9\\.\\-_/~]+",true));
//        _tagList->append(TagListEntry("mailto:[a-z0-9\\.\\-_]+@[a-z0-9\\.\\-_]+",true));
//        _tagList->append(TagListEntry("<?[a-z0-9\\.\\-_]+@[a-z0-9\\.\\-_]+>?",true));
//         _tagList->append(TagListEntry("&[a-z,A-Z,\\-,0-9,#]*;",true));
    }

    return _tagList;
}

QStringList *TagExtractor::tagExpressions()
{
    QStringList *list = new QStringList;
    
    TagExtractor::tagList();
    
    if(_tagList)
	for( QValueListIterator<TagListEntry> it = _tagList->begin(); it != _tagList->end() ; ++it )
	    list->append( (*it).asString() );

    return list;
}

void TagExtractor::setTagExpressions( QStringList* list )
{
    _tagList = sdTL.setObject( new QValueList<TagListEntry> );
    for( QStringList::Iterator it = list->begin() ; it != list->end() ; ++it )
        _tagList->append(TagListEntry( *it,true));
}
