/* ****************************************************************************
  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 "argextractor.h"

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

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

ArgListEntry::ArgListEntry(QString t,bool is)
    : arg(t)
    , reg(t,false)
    , isReg(is)
{
}

QString ArgListEntry::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(arg);
        if(index >= 0)
        {
            return arg;
        }
    }

    return QString::null;
}

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

    return true;
}
    

ArgExtractor::ArgExtractor(QString string)
{
    _string=string;
    _args.setAutoDelete(true);

    processString();  
}

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

uint ArgExtractor::countArgs()
{
    return _args.count();
}

QString ArgExtractor::firstArg()
{
    ArgInfo *ti = _args.first();

    if(ti)
        return ti->arg;

    return QString::null;
}

QString ArgExtractor::nextArg()
{
    ArgInfo *ti=_args.next();
    if(!ti)
        ti=_args.first();
    
    if(ti)
        return ti->arg;

    return QString::null;
}

QString ArgExtractor::arg(uint argnumber)
{
    ArgInfo *ti=_args.at(argnumber);
    if(ti)
        return ti->arg;

    return QString::null;
}

QString ArgExtractor::prevArg()
{
    ArgInfo *ti=_args.prev();
    if(ti)
        return ti->arg;
    
    return QString::null;
}

QString ArgExtractor::lastArg()
{
    ArgInfo *ti=_args.last();
    if(ti)
        return ti->arg;
    
    return QString::null;
} 

QStringList ArgExtractor::args()
{
    QStringList list;
    ArgInfo *ti;
    for(ti=_args.first(); ti!=0; ti = _args.next())
    {
        list.append(ti->arg);
    }

    return list;
}

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

    ArgInfo *ti;
    for(ti=_args.first(); ti != 0; ti=_args.next())
    {
        uint len=ti->arg.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 ArgExtractor::argsReplaced(const QString& replace)
{    
    QString tmp=_string;

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

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

    return tmp;
}


void ArgExtractor::addArgIdentifier(QString arg,bool isRegExp)
{
    argList()->append(ArgListEntry(arg,isRegExp));
}

void ArgExtractor::deleteArgIdentifier(QString arg,bool isRegExp)
{
    argList()->remove(ArgListEntry(arg,isRegExp));
}
 

void ArgExtractor::processString()
{
    _args.clear();

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

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

                QString s;
                for(uint i=0; i<arg.length(); i++)
                {
                    s+=' ';
                }
                tmp.replace(pos,arg.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<ArgInfo>::Iterator it;    
        for(it=tmpList.begin();it!=tmpList.end();++it)
        {
            if((*it).index < min)
            {
                min=(*it).index;
                n=counter;
            }
            
            counter++;
        }

        it=tmpList.at(n);
        ArgInfo *ti = new ArgInfo;
        ti->index=(*it).index;
        ti->arg=(*it).arg;
        _args.append(ti);
        tmpList.remove(it);
    }

}

QValueList<ArgListEntry> *ArgExtractor::_argList=0;
KStaticDeleter< QValueList<ArgListEntry> > sdAL;

QValueList<ArgListEntry> *ArgExtractor::argList()
{
    if(!_argList)
    {
        _argList = sdAL.setObject( new QValueList<ArgListEntry> );
        //Build the default arg list
        _argList->append(ArgListEntry("%[ndioxXucsfeEgGp]",true));
        _argList->append(ArgListEntry("%([0-9]+(\\$))?[-+'#0]?[0-9]*(.[0-9]+)?[hlL]?[dioxXucsfeEgGp]",true));  
        _argList->append(ArgListEntry("%[0-9]+",true));
    }

    return _argList;
}

QStringList *ArgExtractor::argExpressions()
{
    QStringList *list = new QStringList;
    
    ArgExtractor::argList();
    
    if(_argList)
	for( QValueListIterator<ArgListEntry> it = _argList->begin(); it != _argList->end() ; ++it )
	    list->append( (*it).asString() );

    return list;
}

void ArgExtractor::setArgExpressions( QStringList* list )
{
    _argList = sdAL.setObject( new QValueList<ArgListEntry> );
    for( QStringList::Iterator it = list->begin() ; it != list->end() ; ++it )
        _argList->append(ArgListEntry( *it,true));
}
