/***************************************************************************
                          mymoneysplit.cpp  -  description
                             -------------------
    begin                : Sun Apr 28 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.                                   *
 *                                                                         *
 ***************************************************************************/

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

#include "mymoneysplit.h"
#include "mymoneytransaction.h"

const char MyMoneySplit::ActionCheck[] = "Check";
const char MyMoneySplit::ActionDeposit[] = "Deposit";
const char MyMoneySplit::ActionTransfer[] = "Transfer";
const char MyMoneySplit::ActionWithdrawal[] = "Withdrawal";
const char MyMoneySplit::ActionATM[] = "ATM";

const char MyMoneySplit::ActionAmortization[] = "Amortization";
const char MyMoneySplit::ActionInterest[] = "Interest";

const char MyMoneySplit::ActionBuyShares[] = "Buy";
const char MyMoneySplit::ActionDividend[] = "Dividend";
const char MyMoneySplit::ActionReinvestDividend[] = "Reinvest";
const char MyMoneySplit::ActionYield[] = "Yield";
const char MyMoneySplit::ActionAddShares[] = "Add";
const char MyMoneySplit::ActionSplitShares[] = "Split";

MyMoneySplit::MyMoneySplit()
{
  m_reconcileFlag = NotReconciled;
}

MyMoneySplit::MyMoneySplit(const TQDomElement& node) :
  MyMoneyObject(node, false),
  MyMoneyKeyValueContainer(node.elementsByTagName("KEYVALUEPAIRS").item(0).toElement())
{
  if("SPLIT" != node.tagName())
    throw new MYMONEYEXCEPTION("Node was not SPLIT");

  clearId();

  m_payee = TQStringEmpty(node.attribute("payee"));
  m_reconcileDate = stringToDate(TQStringEmpty(node.attribute("reconciledate")));
  m_action = TQStringEmpty(node.attribute("action"));
  m_reconcileFlag = static_cast<MyMoneySplit::reconcileFlagE>(node.attribute("reconcileflag").toInt());
  m_memo = TQStringEmpty(node.attribute("memo"));
  m_value = MyMoneyMoney(TQStringEmpty(node.attribute("value")));
  m_shares = MyMoneyMoney(TQStringEmpty(node.attribute("shares")));
  m_price = MyMoneyMoney(TQStringEmpty(node.attribute("price")));
  m_account = TQStringEmpty(node.attribute("account"));
  m_number = TQStringEmpty(node.attribute("number"));
  m_bankID = TQStringEmpty(node.attribute("bankid"));
}

MyMoneySplit::MyMoneySplit(const TQString& id, const MyMoneySplit& right) :
  MyMoneyObject(id)
{
  *this = right;
  setId(id);
}

MyMoneySplit::~MyMoneySplit()
{
}

bool MyMoneySplit::operator == (const MyMoneySplit& right) const
{
  return MyMoneyObject::operator==(right) &&
    MyMoneyKeyValueContainer::operator==(right) &&
    m_account == right.m_account &&
    m_payee == right.m_payee &&
    m_memo == right.m_memo &&
    m_action == right.m_action &&
    m_reconcileDate == right.m_reconcileDate &&
    m_reconcileFlag == right.m_reconcileFlag &&
    ((m_number.length() == 0 && right.m_number.length() == 0) || m_number == right.m_number) &&
    m_shares == right.m_shares &&
    m_value == right.m_value &&
    m_price == right.m_price &&
    m_transactionId == right.m_transactionId;
}

void MyMoneySplit::setAccountId(const TQString& account)
{
  m_account = account;
}

void MyMoneySplit::setMemo(const TQString& memo)
{
  m_memo = memo;
}

void MyMoneySplit::setReconcileDate(const TQDate& date)
{
  m_reconcileDate = date;
}

void MyMoneySplit::setReconcileFlag(const reconcileFlagE flag)
{
  m_reconcileFlag = flag;
}

void MyMoneySplit::setShares(const MyMoneyMoney& shares)
{
  m_shares = shares;
}

void MyMoneySplit::setValue(const MyMoneyMoney& value)
{
  m_value = value;
}

void MyMoneySplit::setValue(const MyMoneyMoney& value, const TQString& transactionCurrencyId, const TQString& splitCurrencyId)
{
  if(transactionCurrencyId == splitCurrencyId)
    setValue(value);
  else
    setShares(value);
}

void MyMoneySplit::setPayeeId(const TQString& payee)
{
  m_payee = payee;
}

void MyMoneySplit::setAction(investTransactionTypeE type)
{
  switch(type) {
    case BuyShares:
    case SellShares:
      setAction(ActionBuyShares);
      break;
    case Dividend:
      setAction(ActionDividend);
      break;
    case Yield:
      setAction(ActionYield);
      break;
    case ReinvestDividend:
      setAction(ActionReinvestDividend);
      break;
    case AddShares:
    case RemoveShares:
      setAction(ActionAddShares);
      break;
    case MyMoneySplit::SplitShares:
      setAction(ActionSplitShares);
      break;
    case MyMoneySplit::UnknownTransactionType:
      break;
  }
}

void MyMoneySplit::setAction(const TQString& action)
{
  m_action = action;
}

void MyMoneySplit::setNumber(const TQString& number)
{
  m_number = number;
}

const MyMoneyMoney MyMoneySplit::value(const TQString& transactionCurrencyId, const TQString& splitCurrencyId) const
{
  return (transactionCurrencyId == splitCurrencyId) ? m_value : m_shares;
}

void MyMoneySplit::setPrice(const MyMoneyMoney& price)
{
  m_price = price;
}

MyMoneyMoney MyMoneySplit::price(void) const
{
  if(!m_price.isZero())
    return m_price;
  if(!m_value.isZero() && !m_shares.isZero())
    return m_value / m_shares;
  return MyMoneyMoney(1,1);
}

void MyMoneySplit::writeXML(TQDomDocument& document, TQDomElement& parent) const
{
  TQDomElement el = document.createElement("SPLIT");

  writeBaseXML(document, el);

  el.setAttribute("payee", m_payee);
  el.setAttribute("reconciledate", dateToString(m_reconcileDate));
  el.setAttribute("action", m_action);
  el.setAttribute("reconcileflag", m_reconcileFlag);
  el.setAttribute("value", m_value.toString());
  el.setAttribute("shares", m_shares.toString());
  if(!m_price.isZero())
    el.setAttribute("price", m_price.toString());
  el.setAttribute("memo", m_memo);
  // No need to write the split id as it will be re-assigned when the file is read
  // el.setAttribute("id", split.id());
  el.setAttribute("account", m_account);
  el.setAttribute("number", m_number);
  el.setAttribute("bankid", m_bankID);

  MyMoneyKeyValueContainer::writeXML(document, el);

  parent.appendChild(el);
}

bool MyMoneySplit::hasReferenceTo(const TQString& id) const
{
  bool rc = false;
  if(isMatched()) {
    rc = matchedTransaction().hasReferenceTo(id);
  }
  return rc || (id == m_account) || (id == m_payee);
}

bool MyMoneySplit::isMatched(void) const
{
  return !(value("kmm-matched-tx").isEmpty());
}

void MyMoneySplit::addMatch(const MyMoneyTransaction& _t)
{
  if(_t.isImported() && !isMatched()) {
    MyMoneyTransaction t(_t);
    t.clearId();
    TQDomDocument doc("MATCH");
    TQDomElement el = doc.createElement("CONTAINER");
    doc.appendChild(el);
    t.writeXML(doc, el);
    TQString xml = doc.toString();
    xml.replace("<", "&lt;");
    setValue("kmm-matched-tx", xml);
  }
}

void MyMoneySplit::removeMatch(void)
{
  deletePair("kmm-matched-tx");
}

MyMoneyTransaction MyMoneySplit::matchedTransaction(void) const
{
  TQString xml = value("kmm-matched-tx");
  if(!xml.isEmpty()) {
    xml.replace("&lt;", "<");
    TQDomDocument doc;
    TQDomElement node;
    doc.setContent(xml);
    node = doc.documentElement().firstChild().toElement();
    MyMoneyTransaction t(node, false);
    return t;
  }
  return MyMoneyTransaction();
}
