#include <tqlistview.h>
#include <tqlayout.h>
#include <tqheader.h>

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

#include "bugsystem.h"
#include "kbbprefs.h"
#include "bugserver.h"

#include "packagelvi.h"
#include "packageselectdialog.h"
#include "packageselectdialog.moc"

PackageListView::PackageListView( TQWidget *parent ) :
    TQListView( parent )
{
    setFocusPolicy( TQWidget::StrongFocus );
}

void PackageListView::resetTyped()
{
    mTyped = "";
}

void PackageListView::keyPressEvent( TQKeyEvent *e )
{
    // Disable listview text completion for now
    TQListView::keyPressEvent( e );
    return;

    int k = e->key();
    if ( k == Key_Return || k == Key_Escape ) e->ignore();

    TQString key = e->text();
    mTyped.append(key);
    emit typed( mTyped );
}

PackageSelectDialog::PackageSelectDialog(TQWidget *parent,const char *name) :
  KDialogBase( parent, name, true, i18n("Select Product"), Ok|Cancel )
{
    TQWidget *topWidget = new TQWidget( this );
    setMainWidget( topWidget );

    TQBoxLayout *topLayout = new TQVBoxLayout( topWidget );
    TQSplitter *topSplitter = new TQSplitter( TQt::Vertical, topWidget );
    topSplitter->setOpaqueResize( true );

    topLayout->addWidget( topSplitter );

    mRecentList = new TQListView( topSplitter );
    mRecentList->addColumn( i18n("Recent") );
    mRecentList->resize( mRecentList->width(), mRecentList->fontMetrics().height() *
			 KBBPrefs::instance()->mRecentPackagesCount );
    
    connect( mRecentList, TQ_SIGNAL( mouseButtonPressed( int, TQListViewItem *, const TQPoint &, int) ),
             TQ_SLOT( recentSelected( int, TQListViewItem * ) ) );
    connect( mRecentList, TQ_SIGNAL( doubleClicked( TQListViewItem * ) ),
             TQ_SLOT( slotOk() ) );

    mCompletion = new TDECompletion;
    mCompletion->setCompletionMode( TDEGlobalSettings::CompletionAuto );

    mCompleteList = new PackageListView( topSplitter );
    mCompleteList->addColumn( i18n("Name") );
    mCompleteList->addColumn( i18n("Description") );
    mCompleteList->setRootIsDecorated(true);
    mCompleteList->setAllColumnsShowFocus( true );
    connect( mCompleteList, TQ_SIGNAL( typed( const TQString & ) ),
             TQ_SLOT( completeTyped( const TQString & ) ) );


    connect( mCompleteList, TQ_SIGNAL( mouseButtonPressed( int, TQListViewItem *, const TQPoint &, int) ),
             TQ_SLOT( completeSelected( int, TQListViewItem * ) ) );
    connect( mCompleteList, TQ_SIGNAL( doubleClicked( TQListViewItem * ) ),
             TQ_SLOT( slotOk() ) );

    mPackageEdit = new KLineEdit( topWidget );
    mPackageEdit->setFocus();

    topLayout->addWidget( mPackageEdit );
    connect( mPackageEdit, TQ_SIGNAL( textChanged( const TQString & ) ),
             TQ_SLOT( completeTyped( const TQString & ) ) );
    enableButtonOK( !mPackageEdit->text().isEmpty() );
}

PackageSelectDialog::~PackageSelectDialog()
{
    delete mCompletion;
}

void PackageSelectDialog::setRecentPackages( const TQStringList &recent )
{
    mRecentList->clear();
    TQStringList::ConstIterator it;
    for( it = recent.begin(); it != recent.end(); ++it ) {
        new TQListViewItem( mRecentList, *it );
    }
}

void PackageSelectDialog::setPackages( const Package::List &pkgs )
{
    mCompleteList->clear();
    mCompletion->clear();
    mCompletionDict.clear();
    Package::List::ConstIterator it;
    for( it = pkgs.begin(); it != pkgs.end(); ++it ) {
        PackageLVI *item = new PackageLVI( mCompleteList, (*it), TQString() );
        TQStringList components = (*it).components();

        if (components.count() > 1) {
           for( TQStringList::ConstIterator cit = components.begin(); cit != components.end(); ++cit ) {
               PackageLVI *component = new PackageLVI( item, (*it), (*cit) );
               TQString completionName = (*it).name() + "/" + (*cit);

               mCompletion->addItem( completionName );
               mCompletionDict.insert( completionName, component );
           }
        }

        mCompletion->addItem( (*it).name() );
        mCompletionDict.insert((*it).name(),item);
    }
}

void PackageSelectDialog::recentSelected( int, TQListViewItem *item )
{
    kdDebug() << "PackageSelectDialog::recentSelected()" << endl;
    if ( item ) {
        mCompleteList->clearSelection();
        // Why does a TQLineEdit->setText() call emit the textChanged() signal?
        mPackageEdit->blockSignals( true );
        mPackageEdit->setText( item->text( 0 ) );
        enableButtonOK(true);
        mPackageEdit->blockSignals( false );
    }
}

void PackageSelectDialog::completeSelected( int, TQListViewItem *item )
{
    PackageLVI *lvi = dynamic_cast<PackageLVI*>(item);

    if ( lvi ) {
        mRecentList->clearSelection();
        if ( lvi->component().isEmpty() ) {
            mPackageEdit->setText( lvi->package().name() );
        }
        else {
            mPackageEdit->setText( lvi->package().name() + "/" + lvi->component() );
        }
    }
}

void PackageSelectDialog::slotOk()
{
    PackageLVI *item = (PackageLVI *)mCompleteList->selectedItem();
    if ( item ) {
        mSelectedPackage = item->package();
        mSelectedComponent = item->component();

        TQString recent_key;
        if ( item->component().isEmpty() )
            recent_key = item->package().name();
        else
            recent_key = item->package().name() + "/" + item->component();

        BugServer *server = BugSystem::self()->server();
        TQStringList recent = server->serverConfig().recentPackages();
        if( !recent.contains( recent_key ) ) {
            recent.prepend( recent_key );
            if ( int( recent.count() ) > KBBPrefs::instance()->mRecentPackagesCount ) {
                recent.remove( recent.last() );
            }
            kdDebug() << "RECENT: " << recent.join(",") << endl;
            server->serverConfig().setRecentPackages( recent );
        }
    } else {
        TQListViewItem *recentItem = mRecentList->selectedItem();
        if ( recentItem ) {
            TQStringList tokens = TQStringList::split( '/', recentItem->text( 0 ) );
            mSelectedPackage = BugSystem::self()->package( tokens[0] );
            mSelectedComponent = tokens[1];
        }
    }
    mCompleteList->resetTyped();
    accept();
}

Package PackageSelectDialog::selectedPackage()
{
    return mSelectedPackage;
}

TQString PackageSelectDialog::selectedComponent()
{
    return mSelectedComponent;
}

void PackageSelectDialog::completeTyped( const TQString &typed )
{
    kdDebug() << "completeTyped: " << typed << endl;
    TQString completed = mCompletion->makeCompletion( typed );
    kdDebug() << "completed:     " << completed << endl;
    if ( !completed.isEmpty() ) {
      mCompleteList->setSelected( mCompletionDict[ completed ], true );
      mCompleteList->ensureItemVisible( mCompletionDict[ completed ] );
    } else {
      mCompleteList->resetTyped();
    }
    enableButtonOK( !typed.isEmpty() );
}
