/***************************************************************************
                          keditloanwizard.cpp  -  description
                             -------------------
    begin                : Wed Nov 12 2003
    copyright            : (C) 2000-2003 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 <tqradiobutton.h>
#include <tqbuttongroup.h>
#include <tqlabel.h>

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

#include <tdelocale.h>
#include <tdemessagebox.h>
#include <knuminput.h>
#include <kpushbutton.h>

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

#include <../dialogs/knewloanwizard.h>
#include "keditloanwizard.h"
#include "../widgets/kmymoneylineedit.h"
#include "../widgets/kmymoneyedit.h"
#include "../widgets/kmymoneycombo.h"
#include "../widgets/kmymoneyaccountselector.h"
#include "../widgets/kmymoneydateinput.h"
#include "../mymoney/mymoneyfile.h"
#include "../kmymoneyutils.h"

KEditLoanWizard::KEditLoanWizard(const MyMoneyAccount& account, TQWidget *parent, const char *name ) :
  KNewLoanWizard(parent, name)
{
  MyMoneyFile* file = MyMoneyFile::instance();

  setCaption(i18n("Edit loan wizard"));
  m_effectiveDateLabel->setText(TQString("\n") + i18n(
            "Please enter the date from which on the following changes will be effective. "
            "The date entered must be later than the opening date of this account (%1), but must "
            "not be in the future. The default will be today.").arg(TDEGlobal::locale()->formatDate(account.openingDate(), true)));
  m_account = account;
  try {
    TQString id = m_account.value("schedule");
    m_schedule = file->schedule(id);
  } catch (MyMoneyException *e) {
    delete e;
  }

  m_lastSelection = -1;
  m_editInterestRateButton->animateClick();

  loadWidgets(m_account);

  if(m_account.openingDate() > TQDate::currentDate()) {
    m_effectiveDateNoteLabel->setText(TQString("\n") + i18n(
            "Note: you will not be able to modify this account today, because the opening date \"%1\" is in the future. "
            "Please revisit this dialog when the time has come."
            ).arg(TDEGlobal::locale()->formatDate(m_account.openingDate(), true)));
  } else {
    m_effectiveDateNoteLabel->hide();
  }
  // turn off all pages that are contained here for derived classes
  setAppropriate(m_newIntroPage, false);
  setAppropriate(m_newGeneralInfoPage, false);
  setAppropriate(m_lendBorrowPage, false);
  setAppropriate(m_namePage, false);
  setAppropriate(m_newCalculateLoanPage, false);
  setAppropriate(m_newPaymentsPage, false);
  removePage(m_assetAccountPage);
  m_assetAccountPage = 0;

  // turn on all pages that are contained here for derived classes
  setAppropriate(m_editIntroPage, true);
  setAppropriate(m_editSelectionPage, true);

  // setup connections
  connect(m_effectiveChangeDateEdit, TQT_SIGNAL(dateChanged(const TQDate&)), this, TQT_SLOT(slotCheckPageFinished()));
  connect(m_newPaymentEdit, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotCheckPageFinished()));
  connect(m_newInterestRateEdit, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotCheckPageFinished()));

  // make sure, we show the correct start page
  showPage(m_editIntroPage);
}

KEditLoanWizard::~KEditLoanWizard()
{
}

void KEditLoanWizard::loadWidgets(const MyMoneyAccount& /* account */)
{
  MyMoneyFile* file = MyMoneyFile::instance();
  TQString paymentAccountId, interestAccountId;

  m_nameEdit->loadText(m_account.name());
  m_loanAmountEdit->loadText(m_account.loanAmount().formatMoney(m_account.fraction(MyMoneyFile::instance()->security(m_account.currencyId()))));
  m_finalPaymentEdit->loadText(m_account.finalPayment().formatMoney(m_account.fraction(MyMoneyFile::instance()->security(m_account.currencyId()))));
  m_firstDueDateEdit->setDate(m_account.openingDate());

  if(m_account.fixedInterestRate()) {
    m_fixedInterestButton->animateClick();
  } else {
    m_variableInterestButton->animateClick();
  }

  MyMoneyMoney ir;
  if(m_schedule.startDate() > TQDate::currentDate()) {
    ir = m_account.interestRate(m_schedule.startDate());
  } else {
    ir = m_account.interestRate(TQDate::currentDate());
  }
  m_interestRateEdit->loadText(ir.formatMoney("", 3));
  m_newInterestRateEdit->loadText(ir.formatMoney("", 3));
  m_newInterestRateEdit->setPrecision(3);
  m_interestRateLabel->setText(TQString(" ") + ir.formatMoney("", 3) + TQString("%"));

  m_paymentFrequencyUnitEdit->setCurrentItem(i18n(m_schedule.occurenceToString()));
  updateTermWidgets(m_account.term());

  // the base payment (amortization and interest) is determined
  // by adding all splits that are not automatically calculated.
  // If the loan is a liability, we reverse the sign at the end
  MyMoneyMoney basePayment;
  MyMoneyMoney addPayment;

  m_transaction = m_schedule.transaction();

  TQValueList<MyMoneySplit>::ConstIterator it_s;
  for(it_s = m_schedule.transaction().splits().begin();
      it_s != m_schedule.transaction().splits().end();
      ++it_s) {
    MyMoneyAccount acc = file->account((*it_s).accountId());
    // if it's the split that references the source/dest
    // of the money, we check if we borrow or loan money
    if(paymentAccountId.isEmpty()
    && acc.isAssetLiability() && !acc.isLoan()
    && (*it_s).value() != MyMoneyMoney::autoCalc) {
      if((*it_s).value().isNegative()) {
        m_lendButton->setChecked(false);
        m_borrowButton->setChecked(true);
      } else {
        m_lendButton->setChecked(true);
        m_borrowButton->setChecked(false);
      }
      // we keep the amount of the full payment and subtract the
      // base payment later to get information about the additional payment
      addPayment = (*it_s).value();
      paymentAccountId = (*it_s).accountId();
      MyMoneyPayee payee;
      if(!(*it_s).payeeId().isEmpty()) {
        try {
          payee = file->payee((*it_s).payeeId());
          m_payeeEdit->setSelectedItem(payee.id());
        } catch(MyMoneyException *e) {
          delete e;
          tqWarning("Payee for schedule has been deleted");
        }
      }

      // remove this split with one that will be replaced
      // later and has a phony id
      m_transaction.removeSplit(*it_s);
      m_split.clearId();
      m_transaction.addSplit(m_split);
    }

    if((*it_s).action() == MyMoneySplit::ActionInterest) {
      interestAccountId = (*it_s).accountId();
    }

    if((*it_s).value() != MyMoneyMoney::autoCalc) {
      basePayment += (*it_s).value();
    } else {
      // remove the splits which should not show up
      // for additional fees
      m_transaction.removeSplit(*it_s);
    }

  }
  if(m_borrowButton->isChecked()) {
    basePayment = -basePayment;
    addPayment = -addPayment;
  }
  // now make adjustment to get the amount of the additional fees
  addPayment -= basePayment;

  // load account selection widgets now that we know if
  // we borrow or lend money
  loadAccountList();

  int fraction = m_account.fraction(MyMoneyFile::instance()->security(m_account.currencyId()));
  m_paymentEdit->loadText(basePayment.formatMoney(fraction));
  m_newPaymentEdit->loadText(basePayment.formatMoney(fraction));
  m_paymentLabel->setText(TQString(" ") + basePayment.formatMoney(fraction));

  m_additionalCost->setText(addPayment.formatMoney(fraction));
  m_interestAccountEdit->setSelected(interestAccountId);
  m_paymentAccountEdit->setSelected(paymentAccountId);
  m_nextDueDateEdit->setDate(m_schedule.nextPayment());

  int changeFrequencyUnit;
  int amt = m_account.interestChangeFrequency(&changeFrequencyUnit);
  if(amt != -1) {
    m_interestFrequencyAmountEdit->setValue(amt);
    m_interestFrequencyUnitEdit->setCurrentItem(changeFrequencyUnit);
  }

  // keep track, if the loan should be fully repayed
  m_fullyRepayLoan = m_account.finalPayment() < basePayment;

  updateLoanInfo();
  updateSummary();
}

void KEditLoanWizard::next()
{
  bool dontLeavePage = false;
  TQButton* button = m_selectionButtonGroup->find(m_lastSelection);

  if(currentPage() == m_editSelectionPage) {

    if(button != 0
    && m_lastSelection != m_selectionButtonGroup->id(m_selectionButtonGroup->selected())) {
      TQString errMsg = i18n(
            "Your previous selection was \"%1\". If you select another option, "
            "KMyMoney will dismiss the changes you have just entered. "
            "Do you wish to proceed?").arg(button->text());

      if(KMessageBox::questionYesNo(this, errMsg) == KMessageBox::No) {
        dontLeavePage = true;
      } else {
        loadWidgets(m_account);
      }
    }

    if(!dontLeavePage) {
      button = m_selectionButtonGroup->selected();

      // turn off all pages except the summary at the end
      // and the one's we need for the selected option
      // and load the widgets with the current values

      // general info
      setAppropriate(m_namePage, false);
      setAppropriate(m_interestTypePage, false);
      setAppropriate(m_previousPaymentsPage, false);
      setAppropriate(m_recordPaymentPage, false);
      setAppropriate(m_variableInterestDatePage, false);
      setAppropriate(m_firstPaymentPage, false);
      // loan calculation
      setAppropriate(m_paymentEditPage, false);
      setAppropriate(m_interestEditPage, false);
      setAppropriate(m_paymentFrequencyPage, false);
      setAppropriate(m_interestCalculationPage, false);
      setAppropriate(m_loanAmountPage, false);
      setAppropriate(m_interestPage, false);
      setAppropriate(m_durationPage, false);
      setAppropriate(m_paymentPage, false);
      setAppropriate(m_finalPaymentPage, false);
      setAppropriate(m_calculationOverviewPage, false);
      // payment
      setAppropriate(m_interestCategoryPage, false);
      setAppropriate(m_additionalFeesPage, false);
      setAppropriate(m_schedulePage, false);
      setAppropriate(m_summaryPage, true);

      setAppropriate(m_effectiveDatePage, true);
      if(indexOf(m_summaryPage) != -1) {
        removePage(m_summaryPage);
        setFinishEnabled(m_summaryEditPage, true);
      }

      if(button == m_editInterestRateButton) {
        setAppropriate(m_interestTypePage, true);
        setAppropriate(m_variableInterestDatePage, true);
        setAppropriate(m_paymentEditPage, true);
        setAppropriate(m_interestEditPage, true);
        setAppropriate(m_summaryEditPage, true);

      } else if(button == m_editOtherCostButton) {
        setAppropriate(m_additionalFeesPage, true);
        setAppropriate(m_summaryEditPage, true);

      } else if(button == m_editOtherInfoButton) {
        setAppropriate(m_namePage, true);
        setAppropriate(m_interestCalculationPage, true);
        setAppropriate(m_interestPage, true);
        setAppropriate(m_durationPage, true);
        setAppropriate(m_paymentPage, true);
        setAppropriate(m_finalPaymentPage, true);
        setAppropriate(m_calculationOverviewPage, true);
        setAppropriate(m_interestCategoryPage, true);
        setAppropriate(m_additionalFeesPage, true);
        setAppropriate(m_schedulePage, true);
        setAppropriate(m_summaryEditPage, false);
        addPage(m_summaryPage, i18n("Summary"));
        setAppropriate(m_summaryPage, true);
        setFinishEnabled(m_summaryEditPage, false);
        setFinishEnabled(m_summaryPage, true);

      } else {
        tqFatal("%s,%d: This should never happen", __FILE__, __LINE__);
      }

      m_lastSelection = m_selectionButtonGroup->id(m_selectionButtonGroup->selected());
    } // if(!dontLeavePage)

  } else if(currentPage() == m_additionalFeesPage) {
    button = m_selectionButtonGroup->selected();
    if(button == m_editOtherCostButton) {
      updateLoanInfo();
      updateEditSummary();
    }

  } else if(currentPage() == m_interestEditPage) {
    // copy the necessary data to the widgets used for calculation
    m_interestRateEdit->setValue(m_newInterestRateEdit->value());
    m_paymentEdit->setValue(m_newPaymentEdit->value());

    // if interest rate and payment amount is given, then force
    // the term to be recalculated. The final payment is adjusted to
    // 0 if the loan was ment to be fully repayed
    updateTermWidgets(m_account.term());
    if(!m_interestRateEdit->lineedit()->text().isEmpty()
    && !m_paymentEdit->lineedit()->text().isEmpty()) {
      // if there's an amortization going on, we can evaluate
      // the new term. If the amortization is 0 (interest only
      // payments) then we keep the term as entered by the user.
      if(m_loanAmountEdit->value() != m_finalPaymentEdit->value()) {
        m_durationValueEdit->setValue(0);
      }
      if(m_fullyRepayLoan)
        m_finalPaymentEdit->loadText(MyMoneyMoney(0).formatMoney(m_account.fraction(MyMoneyFile::instance()->security(m_account.currencyId()))));
    }

/*
    // we need to calculate the balance at the time of the change
    // in order to accurately recalculate the term. A special
    // situation arises, when we keep track of all payments and
    // the full loan is not yet paid out. In this case, we take the
    // the loan amount minus all amortization payments as the current
    // balance.
    // FIXME: This needs some more thoughts. We leave it out for
    //        now and always calculate with the full loan amount.
    MyMoneyMoney balance = m_account.openingBalance();

    TQValueList<MyMoneyTransaction> list;
    TQValueList<MyMoneyTransaction>::ConstIterator it;
    MyMoneySplit split;
    MyMoneyTransactionFilter filter(m_account.id());

    filter.setDateFilter(TQDate(), m_effectiveChangeDateEdit->date().addDays(-1));
    list = MyMoneyFile::instance()->transactionList(filter);

    for(it = list.begin(); it != list.end(); ++it) {
      try {
        split = (*it).splitByAccount(m_account.id());
        balance += split.value();

      } catch(MyMoneyException *e) {
        // account is not referenced within this transaction
        delete e;
      }
    }
    m_loanAmountEdit->setText(balance.formatMoney());
*/

    // now re-calculate the figures
    dontLeavePage = !calculateLoan();

    // reset the original loan amount to the widget
    m_loanAmountEdit->setValue(m_account.loanAmount());

    if(!dontLeavePage) {
      updateLoanInfo();
      updateEditSummary();
    }
  }

  if(!dontLeavePage)
    KNewLoanWizard::next();

  // These might have been set by KNewLoanWizard::next()
  setAppropriate(m_previousPaymentsPage, false);
  setAppropriate(m_recordPaymentPage, false);
  // we never need to show this page
  if(currentPage() == m_previousPaymentsPage)
    KNewLoanWizard::next();
}

void KEditLoanWizard::slotCheckPageFinished(void)
{
  KNewLoanWizard::slotCheckPageFinished();

  // if we're on one of the specific edit pages, the next button
  // is enabled. If the values in the edit widgets are not
  // appropriate, we just have to disable it.

  if(currentPage() == m_effectiveDatePage) {
    if(m_effectiveChangeDateEdit->date() < m_account.openingDate()
    || m_effectiveChangeDateEdit->date() > TQDate::currentDate())
      nextButton()->setEnabled(false);

  } else if(currentPage() == m_interestEditPage) {
    if(!m_newPaymentEdit->isValid()
    && !m_newInterestRateEdit->isValid())
      nextButton()->setEnabled(false);
  }
}

void KEditLoanWizard::updateEditSummary(void)
{
  updateSummary();
  m_payment7->setText(m_summaryPeriodicPayment->text());
  m_additionalFees7->setText(m_summaryAdditionalFees->text());
  m_totalPayment7->setText(m_summaryTotalPeriodicPayment->text());
  m_interestRate7->setText(m_summaryInterestRate->text());
  m_startDateChanges->setText(TDEGlobal::locale()->formatDate(m_effectiveChangeDateEdit->date(), true));

  // calculate the number of affected transactions
  MyMoneyTransactionFilter filter(m_account.id());
  filter.setDateFilter(m_effectiveChangeDateEdit->date(), TQDate());

  int count = 0;
  TQValueList<MyMoneyTransaction> list;
  TQValueList<MyMoneyTransaction>::ConstIterator it;
  list = MyMoneyFile::instance()->transactionList(filter);

  for(it = list.begin(); it != list.end(); ++it) {
    TQValueList<MyMoneySplit>::ConstIterator it_s;
    int match = 0;
    for(it_s = (*it).splits().begin(); it_s != (*it).splits().end(); ++it_s) {
      // we only count those transactions that have an interest
      // and amortization part
      if((*it_s).action() == MyMoneySplit::ActionInterest)
        match |= 0x01;
      if((*it_s).action() == MyMoneySplit::ActionAmortization)
        match |= 0x02;
    }
    if(match == 0x03)
      count++;
  }

  m_affectedPayments->setText(TQString().sprintf("%d", count));
}

const MyMoneySchedule KEditLoanWizard::schedule(void) const
{
  MyMoneySchedule sched = m_schedule;
  sched.setTransaction(transaction());
  sched.setOccurence(MyMoneySchedule::stringToOccurence(m_paymentFrequencyUnitEdit->currentText()));
  if(m_nextDueDateEdit->date() < m_schedule.startDate())
    sched.setStartDate(m_nextDueDateEdit->date());

  return sched;
}

const MyMoneyAccount KEditLoanWizard::account(void) const
{
  MyMoneyAccountLoan acc(m_account);

  if(m_interestOnReceptionButton->isChecked())
    acc.setInterestCalculation(MyMoneyAccountLoan::paymentReceived);
  else
    acc.setInterestCalculation(MyMoneyAccountLoan::paymentDue);

  acc.setFixedInterestRate(m_fixedInterestButton->isChecked());
  acc.setFinalPayment(MyMoneyMoney(m_finalPaymentEdit->text()));
  acc.setTerm(term());
  acc.setPeriodicPayment(m_paymentEdit->value());
  acc.setInterestRate(m_effectiveChangeDateEdit->date(), m_interestRateEdit->value());

  acc.setPayee(m_payeeEdit->selectedItem());

  if(m_variableInterestButton->isChecked()) {
    acc.setNextInterestChange(m_interestChangeDateEdit->date());
    acc.setInterestChangeFrequency(m_interestFrequencyAmountEdit->value(),
                                   m_interestFrequencyUnitEdit->currentItem());
  }

  return acc;
}

const MyMoneyTransaction KEditLoanWizard::transaction() const
{
  MyMoneyTransaction t = KNewLoanWizard::transaction();
  MyMoneySplit s = t.splitByAccount(TQString("Phony-ID"));

  s.setAccountId(m_account.id());
  t.modifySplit(s);

  return t;
}

#include "keditloanwizard.moc"
