/***************************************************************************
                          kcategoriesview.cpp  -  description
                             -------------------
    begin                : Sun Jan 20 2002
    copyright            : (C) 2000-2002 by Michael Edwardes
    email                : mte@users.sourceforge.net
                           Javier Campos Morales <javi_c@users.sourceforge.net>
                           Felix Rodriguez <frodriguez@users.sourceforge.net>
                           John C <thetacoturtle@users.sourceforge.net>
                           Thomas Baumgart <ipwizard@users.sourceforge.net>
                           Kevin Tambascio <ktambascio@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.                                   *
 *                                                                         *
 ***************************************************************************/

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

#include <tqlabel.h>
#include <tqlayout.h>

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

#include <klocale.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kguiitem.h>
#include <kpushbutton.h>

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

#include <kmymoney/mymoneyfile.h>
#include <kmymoney/kmymoneyaccounttree.h>
#include "kcategoriesview.h"
#include "../widgets/klistviewsearchline.h"
#include "../kmymoneyglobalsettings.h"
#include "../kmymoney2.h"


KCategoriesView::KCategoriesView(TQWidget *tqparent, const char *name ) :
  KCategoriesViewDecl(tqparent, name),
  m_incomeItem(0),
  m_expenseItem(0),
  m_needReload(false)
{
  // create the searchline widget
  // and insert it into the existing tqlayout
  m_searchWidget = new KListViewSearchLineWidget(m_accountTree, m_accountTree->tqparentWidget());
  TQVBoxLayout* tqlayout = dynamic_cast<TQVBoxLayout*>(m_accountTree->tqparentWidget()->tqlayout());
  if(tqlayout) {
    tqlayout->insertWidget(0, m_searchWidget);
  }

  // setup icons for collapse and expand button
  KIconLoader *ic = KGlobal::iconLoader();
  KGuiItem collapseGuiItem("",
                          TQIconSet(ic->loadIcon("viewmag-", KIcon::Small, KIcon::SizeSmall)),
                          TQString(),
                          TQString());
  KGuiItem expandGuiItem("",
                          TQIconSet(ic->loadIcon("viewmag+", KIcon::Small, KIcon::SizeSmall)),
                          TQString(),
                          TQString());
  m_collapseButton->setGuiItem(collapseGuiItem);
  m_expandButton->setGuiItem(expandGuiItem);

  m_accountTree->setSectionHeader(i18n("Category"));

  connect(m_accountTree, TQT_SIGNAL(selectObject(const MyMoneyObject&)), this, TQT_SIGNAL(selectObject(const MyMoneyObject&)));
  connect(m_accountTree, TQT_SIGNAL(openContextMenu(const MyMoneyObject&)), this, TQT_SIGNAL(openContextMenu(const MyMoneyObject&)));
  connect(m_accountTree, TQT_SIGNAL(valueChanged(void)), this, TQT_SLOT(slotUpdateProfit(void)));
  connect(m_accountTree, TQT_SIGNAL(openObject(const MyMoneyObject&)), this, TQT_SIGNAL(openObject(const MyMoneyObject&)));
  connect(m_accountTree, TQT_SIGNAL(reparent(const MyMoneyAccount&, const MyMoneyAccount&)), this, TQT_SIGNAL(reparent(const MyMoneyAccount&, const MyMoneyAccount&)));

  connect(MyMoneyFile::instance(), TQT_SIGNAL(dataChanged()), this, TQT_SLOT(slotLoadAccounts()));
  connect(m_collapseButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotExpandCollapse()));
  connect(m_expandButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotExpandCollapse()));
}

KCategoriesView::~KCategoriesView()
{
}

void KCategoriesView::slotExpandCollapse(void)
{
  if(sender()) {
    KMyMoneyGlobalSettings::setShowAccountsExpanded(sender() == m_expandButton);
  }
}


void KCategoriesView::show(void)
{
  if(m_needReload) {
    loadAccounts();
    m_needReload = false;
  }

  // don't forget base class implementation
  KCategoriesViewDecl::show();

  // if we have a selected account, let the application know about it
  KMyMoneyAccountTreeBaseItem *item = m_accountTree->selectedItem();
  if(item) {
    emit selectObject(item->itemObject());
  }
}

void KCategoriesView::polish(void)
{
  KCategoriesViewDecl::polish();
  m_accountTree->setResizeMode(TQListView::LastColumn);
  m_accountTree->restoreLayout("Category View Settings");

}

void KCategoriesView::slotLoadAccounts(void)
{
  if(isVisible()) {
    loadAccounts();
  } else {
    m_needReload = true;
  }
}

void KCategoriesView::loadAccounts(void)
{
  TQMap<TQString, bool> isOpen;

  ::timetrace("start load categories view");
  // remember the id of the current selected item
  KMyMoneyAccountTreeBaseItem *item = m_accountTree->selectedItem();
  TQString selectedItemId = (item) ? item->id() : TQString();

  // keep a map of all 'expanded' accounts
  TQListViewItemIterator it_lvi(m_accountTree);
  while(it_lvi.current()) {
    item = dynamic_cast<KMyMoneyAccountTreeItem*>(it_lvi.current());
    if(item && item->isOpen()) {
      isOpen[item->id()] = true;
    }
    ++it_lvi;
  }

  // remember the upper left corner of the viewport
  TQPoint startPoint = m_accountTree->viewportToContents(TQPoint(0, 0));

  // turn off updates to avoid flickering during reload
  m_accountTree->setUpdatesEnabled(false);

  // clear the current contents and recreate it
  m_accountTree->clear();
  m_securityMap.clear();
  m_transactionCountMap.clear();

  // make sure, the pointers are not pointing to some deleted object
  m_incomeItem = m_expenseItem = 0;

  MyMoneyFile* file = MyMoneyFile::instance();

  TQValueList<MyMoneySecurity> slist = file->currencyList();
  slist += file->securityList();
  TQValueList<MyMoneySecurity>::const_iterator it_s;
  for(it_s = slist.begin(); it_s != slist.end(); ++it_s) {
    m_securityMap[(*it_s).id()] = *it_s;
  }

  m_transactionCountMap = file->transactionCountMap();

  bool haveUnusedCategories = false;

  // create the items
  try {
    const MyMoneySecurity& security = file->baseCurrency();
    m_accountTree->setBaseCurrency(security);

    const MyMoneyAccount& income = file->income();
    m_incomeItem = new KMyMoneyAccountTreeItem(m_accountTree, income, security, i18n("Income"));
    haveUnusedCategories |= loadSubAccounts(m_incomeItem, income.accountList());

    const MyMoneyAccount& expense = file->expense();
    m_expenseItem = new KMyMoneyAccountTreeItem(m_accountTree, expense, security, i18n("Expense"));
    haveUnusedCategories |= loadSubAccounts(m_expenseItem, expense.accountList());

  } catch(MyMoneyException *e) {
    kdDebug(2) << "Problem in categoriesview: " << e->what() << endl;
    delete e;
  }

  // scan through the list of accounts and re-expand those that were
  // expanded and re-select the one that was probably selected before
  it_lvi = TQListViewItemIterator(m_accountTree);
  while(it_lvi.current()) {
    item = dynamic_cast<KMyMoneyAccountTreeItem*>(it_lvi.current());
    if(item) {
      if(item->id() == selectedItemId)
        m_accountTree->setSelected(item, true);
      if(isOpen.tqfind(item->id()) != isOpen.end())
        item->setOpen(true);
    }
    ++it_lvi;
  }

  // reposition viewport
  m_accountTree->setContentsPos(startPoint.x(), startPoint.y());

  m_searchWidget->searchLine()->updateSearch(TQString());

  // turn updates back on
  m_accountTree->setUpdatesEnabled(true);
  m_accountTree->tqrepaintContents();

  // and in case we need to show things expanded, we'll do so
  if(KMyMoneyGlobalSettings::showAccountsExpanded())
    m_accountTree->slotExpandAll();

  // update the hint if categories are hidden
  m_hiddenCategories->setShown(haveUnusedCategories);

  ::timetrace("done load categories view");
}

bool KCategoriesView::loadSubAccounts(KMyMoneyAccountTreeItem* tqparent, const TQStringList& accountList)
{
  MyMoneyFile* file = MyMoneyFile::instance();

  bool unused = false;

  TQStringList::const_iterator it_a;
  for(it_a = accountList.begin(); it_a != accountList.end(); ++it_a) {
    const MyMoneyAccount& acc = file->account(*it_a);
    TQValueList<MyMoneyPrice> prices;
    MyMoneySecurity security = file->baseCurrency();
    try {
      if(acc.isInvest()) {
        security = m_securityMap[acc.currencyId()];
        prices += file->price(acc.currencyId(), security.tradingCurrency());
        if(security.tradingCurrency() != file->baseCurrency().id()) {
          MyMoneySecurity sec = m_securityMap[security.tradingCurrency()];
          prices += file->price(sec.id(), file->baseCurrency().id());
        }
      } else if(acc.currencyId() != file->baseCurrency().id()) {
        if(acc.currencyId() != file->baseCurrency().id()) {
          security = m_securityMap[acc.currencyId()];
          prices += file->price(acc.currencyId(), file->baseCurrency().id());
        }
      }

    } catch(MyMoneyException *e) {
      kdDebug(2) << __PRETTY_FUNCTION__ << " caught exception while adding " << acc.name() << "[" << acc.id() << "]: " << e->what();
      delete e;
    }

    KMyMoneyAccountTreeItem* item = new KMyMoneyAccountTreeItem(tqparent, acc, prices, security);
    unused |= loadSubAccounts(item, acc.accountList());

    // no child accounts and not transactions in this account means 'unused'
    bool thisUnused = (!item->firstChild()) && (m_transactionCountMap[acc.id()] == 0);

    // In case of a category which is unused and we are requested to suppress
    // the display of those,
    if(acc.accountGroup() == MyMoneyAccount::Income
    || acc.accountGroup() == MyMoneyAccount::Expense) {
      if(KMyMoneyGlobalSettings::hideUnusedCategory() && thisUnused) {
        unused = true;
        delete item;
      }
    }
  }
  return unused;
}

void KCategoriesView::slotUpdateProfit(void)
{
  if(!m_incomeItem || !m_expenseItem)
    return;

  MyMoneyMoney profit = m_incomeItem->totalValue() - m_expenseItem->totalValue();

  TQString s(i18n("Profit: "));
  if(profit.isNegative())
    s = i18n("Loss: ");

  // FIXME figure out how to deal with the approximate
  // if(!(file->totalValueValid(assetAccount.id()) & file->totalValueValid(liabilityAccount.id())))
  //  s += "~ ";

  s.tqreplace(TQString(" "), TQString("&nbsp;"));
  if(profit.isNegative()) {
    s += "<b><font color=\"red\">";
  }
  const MyMoneySecurity& sec = MyMoneyFile::instance()->baseCurrency();
  TQString v(profit.abs().formatMoney(sec));
  s += v.tqreplace(TQString(" "), TQString("&nbsp;"));
  if(profit.isNegative()) {
    s += "</font></b>";
  }

  m_totalProfitsLabel->setFont(KMyMoneyGlobalSettings::listCellFont());
  m_totalProfitsLabel->setText(s);
}

#include "kcategoriesview.moc"