/* -*- C++ -*-
   This file implements kabīs entry list widget.

   the KDE addressbook

   $ Author: Mirko Boehm $
   $ Copyright: (C) 1996-2000, Mirko Boehm $
   $ Contact: mirko@kde.org
         http://www.kde.org $
   $ License: GPL with the following explicit clarification:
         This code may be linked against any version of the Qt toolkit
         from Troll Tech, Norway. $

   $Revision: 1.3.2.1 $
*/

#include <qstringlist.h>
#include <qcombobox.h>
#include <qcheckbox.h>
#include <qlistbox.h>
#include <kdebug.h>
#include <klocale.h>
#include <klineedit.h>
#include <kcompletion.h>
#include <kapp.h>
#include <knotifyclient.h>
#include "kab_entrylist.h"

KabEntryList::KabEntryList(KabAPI *api_, QWidget *parent, const char* name)
  : KabEntryListBase(parent, name),
    api(api_)
{
  patterns.setAutoDelete(true);
  connect(&timer, SIGNAL(timeout()), SLOT(makeIndex()));
}

void KabEntryList::slotPatternChanged(const QString&)
{
  // ... needed ?
}

void KabEntryList::update(QStringList* list)
{
  const int Interval=500; // msec
  // -----
  kdDebug() << "KabEntryList::update: starting update in background." << endl;
  lbEntries->clear();
  lbEntries->insertStringList(*list);
  if(timer.isActive())
    {
      kdDebug() << "KabEntryList::update: timer pending, restarting." << endl;
      timer.start(Interval, true);
    } else {
      klePattern->setEnabled(false);
      klePattern->setText(i18n("..."));
      klePattern->setCursor(waitCursor);
      timer.start(Interval, true);
    }
  kdDebug() << "KabEntryList::update: done." << endl;
}

void KabEntryList::slotEntrySelected(int index)
{
  emit(entrySelected(index));
}

void KabEntryList::slotPatternEntered(const QString& pattern)
{
  kdDebug() << "KabEntryList::slotPatternEntered: " << pattern
	    << " (possible matches: " << patterns.count() << ")" << endl;
  int index;
  unsigned count;
  // -----
  for(count=0; count<patterns.count(); ++count)
    { 
      if(patterns.at(count)->key()==pattern) break;
    }
  if(count==patterns.count())
    {
      kdDebug() << "KabEntryList::slotPatternEntered: invalid index." << endl;
      emit(setStatus(i18n("No match.")));
      klePattern->setText("");
      KNotifyClient::beep();
      return;
    }
  index=patterns.at(count)->index();
  kdDebug() << "KabEntryList::slotPatternEntered: activating entry " << index 
	    << endl;
  emit(entrySelected(index));
}

void KabEntryList::makeIndex()
{
  klePattern->setText(i18n("Calculating..."));
  // ----- 
  kdDebug() << "KabEntryList::makeIndex: starting." << endl;
  bool avail=false;
  std::list<AddressBook::Entry>::iterator pos;
  AddressBook::Entry entry;
  AddressBook *book=api->addressbook();
  QString text1, text2, desc;
  KCompletion *comp;
  int count;
  unsigned mail;
  // ----- store all entries temporarily:
  if(!entries.empty()) entries.erase(entries.begin(), entries.end());
  // ----- if this happens, update kdelibs to newer than KDE 2.1:
  if(api->getEntries(entries)!=AddressBook::NoError)
    {
      klePattern->setText(i18n("(Disabled)"));
      klePattern->setEnabled(false);
      klePattern->setCursor(forbiddenCursor);
      emit(setStatus(i18n("Error creating index for incremental search.")));
      emit(setStatus(i18n("Incremental search disabled.")));
      if(!entries.empty()) entries.erase(entries.begin(), entries.end());
      return;
    }
  kdDebug() << "KabEntryList::makeIndex: got " << entries.size()
            << " entries from getEntries()." << endl;
  // ----- make the index:
  count=0;
  patterns.clear();
  for(pos=entries.begin(); pos!=entries.end(); ++pos)
    {
      kapp->processEvents();
      // ----- retrieve the strings:
      AddressBook::Entry entry=*pos;
      book->literalName(entry, text1, false, false);
      book->literalName(entry, text2, true, false);
      desc=lbEntries->text(count);
      // ----- remove dots, spaces etc:
      /*
	if(cbIgnoreDots->isChecked())
	{
	// ...
	} else {
	// ...
	}
      */
      // ----- fill the patterns list:
      patterns.append(new Pattern(text1, desc, count));
      patterns.append(new Pattern(text2, desc, count));
      for(mail=0; mail<entry.emails.count(); ++mail)
	{
	  kapp->processEvents();
	  patterns.append(new Pattern(entry.emails[mail], desc, count));
	}
      ++count;
    }
  patterns.sort();
#if 0 // ifndef NDEBUG
  kdDebug() << "KabEntryList::makeIndex: index:" << endl;
  for(unsigned count=0; count<patterns.count(); ++count)
    {
      kdDebug() << "  " << patterns.at(count)->key() << " / "
                << patterns.at(count)->desc() << " / "
                << patterns.at(count)->index() << endl;
    }
  kdDebug() << "KabEntryList::makeIndex: end." << endl;
#endif
  // ----- re-enable line edit if the index contains items:
  avail=!entries.empty();
  klePattern->setText(avail ? QString("") : i18n("(No items to search)"));
  klePattern->setEnabled(avail);
  klePattern->setCursor(avail ? arrowCursor : forbiddenCursor);
  comp=klePattern->completionObject();
  for(unsigned count=0; count<patterns.count(); ++count)
    {
      comp->addItem(patterns.at(count)->key());
    }
  // ----- cleanup:
  if(!entries.empty()) entries.erase(entries.begin(), entries.end());
  kdDebug() << "KabEntryList::makeIndex: done." << endl;
}

#include "kab_entrylist.moc"
