/***************************************************************************
                          registersearchline.cpp
                             -------------------
    copyright            : (C) 2006 by Thomas Baumgart
    email                : ipwizard@users.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

// ----------------------------------------------------------------------------
// QT Includes

#include <tqapplication.h>
#include <tqlabel.h>
#include <tqtoolbutton.h>
#include <tqtimer.h>

// ----------------------------------------------------------------------------
// KDE Includes

#include <tdetoolbar.h>
#include <tdetoolbarbutton.h>
#include <kiconloader.h>
#include <tdelocale.h>

// ----------------------------------------------------------------------------
// Project Includes

#include <registersearchline.h>

using namespace KMyMoneyRegister;

class RegisterSearchLine::RegisterSearchLinePrivate
{
public:
  RegisterSearchLinePrivate() :
    reg(0),
    combo(0),
    queuedSearches(0),
    status(0) {}

  Register* reg;
  TQComboBox* combo;
  TQString search;
  int queuedSearches;
  int status;
};

RegisterSearchLine::RegisterSearchLine(TQWidget* parent, Register* reg, const char* name) :
  KLineEdit(parent, name),
  d(new RegisterSearchLinePrivate)
{
  init(reg);
}

RegisterSearchLine::RegisterSearchLine(TQWidget* parent, const char* name) :
  KLineEdit(parent, name),
  d(new RegisterSearchLinePrivate)
{
  init(0);
}

void RegisterSearchLine::init(Register *reg)
{
  d->reg = reg;
  connect(this, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(queueSearch(const TQString&)));

  TQLabel* label = new TQLabel(i18n("label for status combo", "Stat&us"), parentWidget());
  d->combo = new TQComboBox(parentWidget());
  // don't change the order of the following lines unless updating
  // the case labels in RegisterSearchLine::itemMatches() at the same time
  d->combo->insertItem(SmallIcon("system-run"), i18n("Any status"));
  d->combo->insertItem(SmallIcon("fileimport"), i18n("Imported"));
  d->combo->insertItem(SmallIcon("connect_creating"), i18n("Matched"));
  d->combo->insertItem(SmallIcon("attention"), i18n("Erroneous"));
  d->combo->insertItem(i18n("Not marked"));
  d->combo->insertItem(i18n("Not reconciled"));
  d->combo->insertItem(i18n("Cleared"));
  d->combo->setCurrentItem(0);
  connect(d->combo, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotStatusChanged(int)));

  label->setBuddy(d->combo);

  if(reg) {
    connect(reg, TQT_SIGNAL(destroyed()), this, TQT_SLOT(registerDestroyed()));
    connect(reg, TQT_SIGNAL(itemAdded(RegisterItem*)), this, TQT_SLOT(itemAdded(RegisterItem*)));
  } else {
    setEnabled(false);
  }
}

RegisterSearchLine::~RegisterSearchLine()
{
  delete d;
}

void RegisterSearchLine::setRegister(Register* reg)
{
  if(d->reg) {
    disconnect(d->reg, TQT_SIGNAL(destroyed()), this, TQT_SLOT(registerDestroyed()));
    disconnect(d->reg, TQT_SIGNAL(itemAdded(RegisterItem*)), this, TQT_SLOT(itemAdded(RegisterItem*)));
  }

  d->reg = reg;

  if(reg) {
    connect(reg, TQT_SIGNAL(destroyed()), this, TQT_SLOT(registerDestroyed()));
    connect(reg, TQT_SIGNAL(itemAdded(RegisterItem*)), this, TQT_SLOT(itemAdded(RegisterItem*)));
  }

  setEnabled(reg != 0);
}

void RegisterSearchLine::slotStatusChanged(int status)
{
  d->status = status;
  updateSearch();
}

void RegisterSearchLine::queueSearch(const TQString& search)
{
  d->queuedSearches++;
  d->search = search;
  TQTimer::singleShot(200, this, TQT_SLOT(activateSearch()));
}

void RegisterSearchLine::activateSearch(void)
{
  --(d->queuedSearches);
  if(d->queuedSearches == 0)
    updateSearch(d->search);
}

void RegisterSearchLine::updateSearch(const TQString& s)
{
  if(!d->reg)
    return;

  d->search = s.isNull() ? text() : s;

  // keep track of the current focus item
  RegisterItem* focusItem = d->reg->focusItem();

  bool enabled = d->reg->isUpdatesEnabled();
  d->reg->setUpdatesEnabled(false);

  bool scrollBarVisible = d->reg->verticalScrollBar()->isVisible();

  RegisterItem* p = d->reg->firstItem();
  for(; p; p = p->nextItem()) {
    p->setVisible(itemMatches(p, d->search));
  }
  d->reg->suppressAdjacentMarkers();
  d->reg->updateAlternate();
  d->reg->setUpdatesEnabled(enabled);

  // if focus item is still visible, then make sure we have
  // it on screen
  if(focusItem && focusItem->isVisible()) {
    d->reg->updateContents();
    d->reg->ensureItemVisible(focusItem);
  } else
    d->reg->repaintContents();

  d->reg->updateScrollBars();

  // if the scrollbar's visibility changed, we need to resize the contents
  if(scrollBarVisible != d->reg->verticalScrollBar()->isVisible()) {
    d->reg->resize(DetailColumn);
  }
}

bool RegisterSearchLine::itemMatches(const RegisterItem* item, const TQString& s) const
{
  const Transaction* t = dynamic_cast<const Transaction*>(item);
  if(t && !t->transaction().id().isEmpty()) {
    // Keep the case list of the following switch statement
    // in sync with the logic to fill the combo box in
    // RegisterSearchLine::init()
    switch(d->status) {
      default:
        break;
      case 1:    // Imported
        if(!t->transaction().isImported())
          return false;
        break;
      case 2:    // Matched
        if(!t->split().isMatched())
          return false;
        break;
      case 3:    // Erroneous
        if(t->transaction().splitSum().isZero())
          return false;
        break;
      case 4:    // Not marked
        if(t->split().reconcileFlag() != MyMoneySplit::NotReconciled)
          return false;
        break;
      case 5:    // Not reconciled
        if(t->split().reconcileFlag() != MyMoneySplit::NotReconciled
        && t->split().reconcileFlag() != MyMoneySplit::Cleared)
          return false;
        break;
      case 6:    // Cleared
        if(t->split().reconcileFlag() != MyMoneySplit::Cleared)
          return false;
        break;
    }
  }

  return item->matches(s);
}

void RegisterSearchLine::reset(void)
{
  clear();
  d->combo->setCurrentItem(0);
  slotStatusChanged(0);
}

void RegisterSearchLine::itemAdded(RegisterItem* item) const
{
  item->setVisible(itemMatches(item, text()));
}

void RegisterSearchLine::registerDestroyed(void)
{
  d->reg = 0;
  setEnabled(false);
}


class RegisterSearchLineWidget::RegisterSearchLineWidgetPrivate
{
  public:
  RegisterSearchLineWidgetPrivate() :
    reg(0),
    searchLine(0),
    clearButton(0) {}

  Register* reg;
  RegisterSearchLine* searchLine;
  TQToolButton* clearButton;
};


RegisterSearchLineWidget::RegisterSearchLineWidget(Register* reg, TQWidget* parent, const char* name) :
  TQHBox(parent, name),
  d(new RegisterSearchLineWidgetPrivate)
{
  d->reg = reg;
  setSpacing(5);
  TQTimer::singleShot(0, this, TQT_SLOT(createWidgets()));
}

RegisterSearchLineWidget::~RegisterSearchLineWidget()
{
  delete d;
}

RegisterSearchLine* RegisterSearchLineWidget::createSearchLine(Register* reg)
{
  if(!d->searchLine)
    d->searchLine = new RegisterSearchLine(this, reg);
  return d->searchLine;
}

void RegisterSearchLineWidget::createWidgets(void)
{
  if(!d->clearButton) {
    d->clearButton = new TQToolButton(this);
    TQIconSet icon = SmallIconSet(TQApplication::reverseLayout() ? "clear_left" : "locationbar_erase");
    d->clearButton->setIconSet(icon);
  }

  d->clearButton->show();

  TQLabel *label = new TQLabel(i18n("S&earch:"), this, "tde toolbar widget");

  d->searchLine = createSearchLine(d->reg);
  d->searchLine->show();

  label->setBuddy(d->searchLine);
  label->show();

  connect(d->clearButton, TQT_SIGNAL(clicked()), d->searchLine, TQT_SLOT(reset()));
}

RegisterSearchLine* RegisterSearchLineWidget::searchLine(void) const
{
  return d->searchLine;
}

#include "registersearchline.moc"
