/*
 *  Copyright (C) 2003 Roberto Raggi (roberto@kdevelop.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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 *
 */

#include <kdevproject.h>
#include <kdevpartcontroller.h>
#include <kdevlanguagesupport.h>

#include <tdelistbox.h>
#include <tdelocale.h>
#include <kdebug.h>
#include <kcompletion.h>
#include <klineedit.h>

#include <tqregexp.h>
#include <tqlabel.h>

#include "quickopenclassdialog.h"
#include "quickopen_part.h"
#include "quickopenfunctionchooseform.h"

QuickOpenClassDialog::QuickOpenClassDialog(QuickOpenPart* part, TQWidget* parent, const char* name, bool modal, WFlags fl)
    : QuickOpenDialog( part, parent, name, modal, fl )
{
    nameLabel->setText( i18n("Class &name:") );
    itemListLabel->setText( i18n("Class &list:") );

    findAllClasses( m_items );
    TQStringList_unique( m_items );

    nameEdit->setFocus();

    itemList->insertStringList( m_items );
    itemList->setCurrentItem(0);
}

QuickOpenClassDialog::~QuickOpenClassDialog()
{
}

void QuickOpenClassDialog::slotExecuted( TQListBoxItem* /*item*/ )
{
    accept();
}

void QuickOpenClassDialog::accept()
{
    if( TQListBoxItem* item = itemList->selectedItem() )
    {
        ClassList klasses = findClass( item->text() );
        if( klasses.count() == 1 )
        {
            ClassDom klass = klasses.first();
            int startLine, startColumn;
            klass->getStartPosition( &startLine, &startColumn );
            m_part->partController()->editDocument( KURL( klass->fileName() ), startLine );
            selectClassViewItem( ItemDom(&(*klass)) );
        }
        else if (klasses.count() > 1 )
        {
            //several classes with the same name found
            TQString fileStr;

            QuickOpenFunctionChooseForm fdlg( this, "" );
            fdlg.setCaption(i18n("Select The Location of Class %1").arg(klasses.first()->name()));
            fdlg.textLabel2->setText(i18n("Class name:"));

            for( ClassList::const_iterator it = klasses.constBegin(); it != klasses.constEnd() ; ++it )
            {
                ClassDom klass = *it;
                //assemble class name to display (maybe with scope info and specialization)
                TQString classStr = m_part->languageSupport()->formatModelItem(klass);
                if(klass->hasSpecializationDeclaration())
                  classStr += klass->getSpecializationDeclaration();
                if(!klass->scope().isEmpty())
                  classStr += "   (in " + klass->scope().join("::") + ")";
                fdlg.argBox->insertItem(classStr);

                fileStr = KURL( klass->fileName() ).fileName();
                KURL full_url( klass->fileName() );
                KURL base_url( m_part->project()->projectDirectory()+"/" );
                fdlg.fileBox->insertItem(fileStr);
                fdlg.setRelativePath(fdlg.fileBox->count()-1,
                    KURL::relativeURL( base_url, full_url ));
            }
            if( fdlg.exec() ){
                int id = fdlg.argBox->currentItem();
                if( id>-1 && id < (int) klasses.count() ){
                    ClassDom model = klasses[id];
                    int line, col;
                    model->getStartPosition( &line, &col );
                    selectClassViewItem( ItemDom(&(*model)) );
                    TQString fileNameStr = model->fileName();
                    m_part->partController()->editDocument( KURL(fileNameStr), line );
                }
            }
        }
    }

    TQDialog::accept();
}

void QuickOpenClassDialog::slotReturnPressed( )
{
    maybeUpdateSelection();
    accept();
}

void QuickOpenClassDialog::findAllClasses( TQStringList& lst )
{
    findAllClasses( lst, m_part->codeModel()->globalNamespace() );
}

void QuickOpenClassDialog::findAllClasses( TQStringList& lst, const ClassDom klass )
{
    TQStringList fullName = klass->scope();
    fullName << klass->name();
    lst << fullName.join( "::" );

    const ClassList classList = klass->classList();
    for( ClassList::ConstIterator it=classList.begin(); it!=classList.end(); ++it )
        findAllClasses( lst, *it );
}

void QuickOpenClassDialog::findAllClasses( TQStringList& lst, const NamespaceDom ns )
{
    const NamespaceList namespaceList = ns->namespaceList();
    for( NamespaceList::ConstIterator it=namespaceList.begin(); it!=namespaceList.end(); ++it )
        findAllClasses( lst, *it );

    const ClassList classList = ns->classList();
    for( ClassList::ConstIterator it=classList.begin(); it!=classList.end(); ++it )
        findAllClasses( lst, *it );
}

ClassList QuickOpenClassDialog::findClass( const TQString& name )
{
    TQStringList path = TQStringList::split( "::", name );
    return findClass( path, m_part->codeModel()->globalNamespace() );
}

ClassList QuickOpenClassDialog::findClass( TQStringList& path, const NamespaceDom ns )
{
    ClassList list;
    if( path.isEmpty() )
        return list;

    TQString current = path.front();
    if( ns->hasNamespace(current) )
    {
        path.pop_front();
        list += findClass( path, ns->namespaceByName(current) );
        path.push_front( current );
    }

    if( ns->hasClass(current) )
    {
        path.pop_front();
        list += findClass( path, ns->classByName(current) );
    }

    return list;
}

ClassList QuickOpenClassDialog::findClass( TQStringList& path, const ClassList klasses )
{
    ClassList list;
    if( path.isEmpty() )
    {
        list += klasses;
        return list;
    }

    for (ClassList::const_iterator it = klasses.constBegin(); it != klasses.constEnd(); ++it)
    {
        list += findClass(path, *it);
    }

    return list;
}

ClassList QuickOpenClassDialog::findClass( TQStringList &path, const ClassDom klass )
{
    ClassList list;
    if( path.isEmpty() )
    {
        list << klass;
        return list;
    }

    TQString current = path.front();
    if( klass->hasClass(current) )
    {
        path.pop_front();
        list += findClass( path, klass->classByName(current) );
        path.push_front(current);
    }

    return list;
}

#include "quickopenclassdialog.moc"

