/***************************************************************************
 $RCSfile: transaction.h,v $
                             -------------------
    cvs         : $Id: transaction.h,v 1.11 2003/07/02 23:07:05 aquamaniac Exp $
    begin       : Sat Jun 08 2002
    copyright   : (C) 2002 by Martin Preuss
    email       : openhbci@aquamaniac.de

 ***************************************************************************
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
 *   MA  02111-1307  USA                                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef HBCITRANSACTION_H
#define HBCITRANSACTION_H

/** @file transaction.h
 *
 * @short HBCI::Transaction and its C wrapper @ref HBCI_Transaction. */

#include <openhbci/dllimport.h>
#include <openhbci/date.h>
#include <openhbci/value.h>
#include <openhbci/hbcistringlist.h>
#include <openhbci/abstracttrans.h>

#ifdef __cplusplus
#include <string>
#include <list>
#include <stdio.h>

namespace HBCI {

/**
 * @short Holds all the data of a transaction in %HBCI.
 *
 * This class represents a transaction. It therefore implements two
 * different specifications: <ol>
 * 
 * <li>If this transaction comes from the bank and you retrieved it
 * with the "get transactions" job, then the data in this class comes
 * from the SWIFT MT 940 specification. </li>
 *
 * <li>If you prepare this transaction by yourself in order to send it
 * to the bank as a "bank transfer" job, then the data in this class
 * is interpreted according to the DTAUS0 specification.</li></ol>
 *
 * It is intended to document each member of this class with a
 * reference to the corresponding fields in those two
 * specifications. FIXME: Unfortunately so far only the references to
 * the SWIFT MT940 fields have been added, but DTAUS0 comments will be
 * added soon.
 *
 * The data getters/setters are ordered in the order in which they
 * appear in the SWIFT MT940 Specification (%HBCI Spec. chapter
 * IX.2.8). That specification is therefore the authoritative source
 * of what precisely each data element means. (Unfortunately sometimes
 * the spec is not so precise...)
 *
 * Note that a whole lot of important information wasn't specified in
 * the MT940 itself but only as an additional structure of the
 * "misc. field" Number 86. Those data fields are specified by the ZKA
 * but not SWIFT itself, and therefore it is noted where that field
 * No. 86 comes into play.
 *
 * @author Martin Preuss<openhbci@aquamaniac.de> */
class DLLIMPORT Transaction : AbstractTrans {
private:
  unsigned int _tid;
  int _ourCountryCode;
  string _ourInstCode;
  string _ourId;
  string _ourSuffix;
  int _otherCountryCode;
  string _otherInstCode;
  string _otherId;
  string _otherSuffix;
  list<string> _otherName;
  string _primanota;
  string _transactionKey;
  string _customerReference;
  string _bankReference;
  int _transactionCode;
  list<string> _description;
  string _transactionText;
  Date _date;
  Date _valutaDate;
  Value _value;
  Value _originalValue;
  Value _charge;

public:
  Transaction();
  virtual ~Transaction();

  void dump(FILE *f) const;

  /** @name unique id */
  /*@{*/
  /** unique id of the transaction */
  virtual unsigned int id() const { return _tid;};
  /** set unique id of the transaction */
  virtual void setId(unsigned int i) { _tid=i;};
  /*@}*/

  /** @name Our account */
  /*@{*/
  /** country code of your institute -- not in MT940 */
  int ourCountryCode() const { return _ourCountryCode;};
  /** country code of your institute -- not in MT940 */
  void setOurCountryCode(int i) { _ourCountryCode=i;};

  /** bank code of your institute (BLZ or S.W.I.F.T. code) -- BLZ in
   :25: */
  const string &ourBankCode() const { return _ourInstCode;};
  /** bank code of your institute (BLZ or S.W.I.F.T. code) -- BLZ in
   :25: */
  void setOurBankCode(const string &code) { _ourInstCode=code;};

  /** Your account number; up to 23 characters. Note: possibly
   * including the currency (yes, that's what MT940 says) --
   * Kontonummer in :25: */
  const string &ourAccountId() const { return _ourId;};
  /** Your account number; up to 23 characters. Note: possibly
   * including the currency (yes, that's what MT940 says) --
   * Kontonummer in :25: */
  void setOurAccountId(const string &id) { _ourId=id;};

  /** If your account has subaccounts which are distinguished by
   * different suffixes, then this is that suffix. Otherwise it's
   * empty. -- not in MT940 */
  const string &ourSuffix() const { return _ourSuffix;};
  /** If your account has subaccounts which are distinguished by
   * different suffixes, then this is that suffix. Otherwise it's
   * empty. -- not in MT940 */
  void setOurSuffix(const string &id) { _ourSuffix=id;};
  /*@}*/

  /** @name Date */
  /*@{*/
  /** A date "Valuta" when the transaction was (really?) executed --
   * Datum Valuta/Wertstellung in :61: */
  const Date &valutaDate() const { return _valutaDate;};
  /** A date "Valuta" when the transaction was (really?) executed --
   * Datum Valuta/Wertstellung in :61: */
  void setValutaDate(const Date &d) { _valutaDate=d;};

  /** The date when the transaction was booked. In MT940 spec this
   * has only four characters (no year), so we take the year from
   * the valutaDate(). -- Buchungsdatum in :61: */
  const Date &date() const {return _date;};
  /** The date when the transaction was booked. In MT940 spec this
   * has only four characters (no year), so we take the year from
   * the valutaDate(). -- Buchungsdatum in :61: */
  void setDate(const Date &d) { _date=d;};
  /*@}*/

  /** @name Value */
  /*@{*/
  /** The value of this transaction in the account's currency. --
   * Betrag in :61: */
  const Value &value() const { return _value;};
  /** The value of this transaction in the account's currency. --
   * Betrag in :61: */
  void setValue(const Value &v) { _value=v;};
  /*@}*/

  /** @name Type of Transaction */
  /*@{*/
  /** this is the transaction id that tells you more about the type
   * of transaction (3 character code) -- Buchungsschluessel in :61: */
  const string &transactionKey() const { return _transactionKey;};
  /** this is the transaction id that tells you more about the type
   * of transaction (3 character code) -- Buchungsschluessel in :61: */
  void setTransactionKey(const string &s) { _transactionKey=s;};
  /*@}*/

  /** @name Reference String */
  /*@{*/
  /** Reference string, if the customer (you) has specified
   * one. (E.g. the cheque number.) Otherwise "NONREF". --
   * Kundenreferenz in :61: */
  const string &customerReference() const { return _customerReference; };
  /** Reference string, if the customer (you) has specified
   * one. (E.g. the cheque number.) Otherwise "NONREF". --
   * Kundenreferenz in :61: */
  void setCustomerReference(const string &s) { _customerReference=s;};

  /** Reference string for this transaction given by the bank, if it
   * has given one. Otherwise empty. -- Bankreferenz in :61: */
  const string &bankReference() const { return _bankReference; };
  /** Reference string for this transaction given by the bank, if it
   * has given one. Otherwise empty. -- Bankreferenz in :61: */
  void setBankReference(const string &s) { _bankReference=s;};
  /*@}*/

  /** @name Currency exchange */
  /*@{*/
  /** NOT IMPLEMENTED. If this transaction was in a different
   * currency than your account is in, then this is the transaction
   * value in the original currency. Otherwise zero. Currently NOT
   * IMPLEMENTED in the MT940 parser. -- Ursprungsbetrag in :61: */
  const Value &originalValue() const { return _originalValue;};
  /** NOT IMPLEMENTED. If this transaction was in a different
   * currency than your account is in, then this is the transaction
   * value in the original currency. Otherwise zero. Currently NOT
   * IMPLEMENTED in the MT940 parser. -- Ursprungsbetrag in :61: */
  void setOriginalValue(const Value &v) { _originalValue=v;};

  /** NOT IMPLEMENTED. If this transaction was in a different
   * currency than your account is in, then this is the extra amount
   * charged for currency exchange. Currently NOT IMPLEMENTED in the
   * MT940 parser. -- Gebührenbetrag (charges) in :61: */
  const Value &charge() const { return _charge;};
  /** NOT IMPLEMENTED. If this transaction was in a different
   * currency than your account is in, then this is the extra amount
   * charged for currency exchange. Currently NOT IMPLEMENTED in the
   * MT940 parser. -- Gebührenbetrag (charges) in :61: */
  void setCharge(const Value &v) { _charge=v;};
  /*@}*/

  /* Now follows the obnoxious "Mehrzweckfeld :86:" */

  /** @name Transaction Description */
  /*@{*/
  /** A 3 digit numerical transaction code, defined for all kinds of
   * different HBCI actions. -- Geschaeftsvorfallcode, first field
   * in field :86:
   * For a normal transfer you should set it to 51. For debit notes the
   * values 05 or 06 may be used. For other values please refer to your
   * credit institute.
   */
  int transactionCode() const { return _transactionCode;};
  /** A 3 digit numerical transaction code, defined for all kinds of
   * different HBCI actions. -- Geschaeftsvorfallcode, first field
   * in field :86:
   * For a normal transfer you should set it to 51. For debit notes the
   * values 05 or 06 may be used. For other values please refer to your
   * credit institute.
   */
  void setTransactionCode(int c) { _transactionCode=c;};

  /** Transaction text (e.g. STANDING ORDER) -- Buchungstext; field
   * 00 in field :86: */
  const string &transactionText() const { return _transactionText;};
  /** Transaction text (e.g. STANDING ORDER) -- Buchungstext; field
   * 00 in field :86: */
  void setTransactionText(const string &s) { _transactionText=s;};

  /** Primanoten-Number (no idea what this means) --
   * Primanoten-Nummer; field 10 in field :86:  */
  const string &primanota() const { return _primanota;};
  /** Primanoten-Number (no idea what this means) --
   * Primanoten-Nummer; field 10 in field :86:  */
  void setPrimanota(const string &s) { _primanota=s;};

  /** Description of what this transaction is for, and how the Bank
   * describes this transaction.
   *
   * According to HBCI Spec chapter IX.2.8, somewhere in these lines
   * this might contain the equivalent transaction value in DEM
   * vs. EUR or vice versa. Also, if the originalValue() and
   * charge() above was unused but this in fact had a original value
   * and charges, then that information might be contained somewhere
   * in these description lines. (Good luck.)
   *
   * -- Verwendungszweck; fields 20-29 and 60-63 in field :86:  */
  const list<string> &description() const { return _description;};
  /** Description of what this transaction is for, and how the Bank
   * describes this transaction.
   *
   * Note: Every single string represents one line, and each line is
   * going to be truncated to have at most 27 characters.
   *
   * According to HBCI Spec chapter IX.2.8, somewhere in these lines
   * this might contain the equivalent transaction value in DEM
   * vs. EUR or vice versa. Also, if the originalValue() and
   * charge() above was unused but this in fact had a original value
   * and charges, then that information might be contained somewhere
   * in these description lines. (Good luck.)
   *
   * -- Verwendungszweck; fields 20-29 and 60-63 in field :86:  */
  void addDescription(const string &s) { _description.push_back(s);};
  /*@}*/

  /** @name Other account */
  /*@{*/
  /** Country code (BLZ) of the other party's institute -- not in
   * MT940/field :86: */
  int otherCountryCode() const { return _otherCountryCode;};
  /** Country code (BLZ) of the other party's institute -- not in
   * MT940/field :86: */
  void setOtherCountryCode(int i) { _otherCountryCode=i;};

  /** Institute code (BLZ) of the other party's institute -- BLZ;
   * field 30 in field :86: */
  const string &otherBankCode() const { return _otherInstCode;};
  /** Institute code (BLZ) of the other party's institute -- BLZ;
   * field 30 in field :86: */
  void setOtherBankCode(const string &s) { _otherInstCode=s;};

  /** Account number of the other party -- Kontonummer; field 31 in
   * field :86: */
  const string &otherAccountId() const { return _otherId;};
  /** Account number of the other party -- Kontonummer; field 31 in
   * field :86: */
  void setOtherAccountId(const string &s) { _otherId=s;};

  /** If the account of the other party has subaccounts which are
   * distinguished by different suffixes, then this is that suffix
   * of the other party. Otherwise it's empty. -- *not* in MT940 /
   * field :86: */
  const string &otherSuffix() const { return _otherSuffix;};
  /** If the account of the other party has subaccounts which are
   * distinguished by different suffixes, then this is that suffix
   * of the other party. Otherwise it's empty. -- *not* in MT940 /
   * field :86: */
  void setOtherSuffix(const string &id) { _otherSuffix=id;};

  /** Name of the other party -- fields 32 and 33 in field :86: */
  const list<string> &otherName() const { return _otherName;};
  /** Name of the other party -- fields 32 and 33 in field :86:
   * Each single string (there are two strings allowed) is going
   * to be truncated to have at most 27 characters. */
  void addOtherName(const string &s) { _otherName.push_back(s);};
  /*@}*/

  /**
   * Compares this Transaction to the given one.
   * @author Martin Preuss<openhbci@aquamaniac.de>
   */
  bool operator==(const Transaction &tda) const;

};

} /* namespace HBCI */

/** @ingroup HBCI_Transactiong
 * @short C accessibly type of HBCI::Transaction */
typedef struct HBCI::Transaction HBCI_Transaction;
/* for C wrapper functions */
/** @ingroup HBCI_Transactiong */
typedef list<HBCI::Transaction> list_HBCI_Transaction;
/** @ingroup HBCI_Transactiong */
typedef list<HBCI::Transaction>::const_iterator list_HBCI_Transaction_iter;

extern "C" {    
#else /* __cplusplus */
typedef struct HBCI_Transaction HBCI_Transaction;
typedef struct list_HBCI_Transaction list_HBCI_Transaction;
typedef struct list_HBCI_Transaction_iter list_HBCI_Transaction_iter;
#endif /* __cplusplus */

    /** @defgroup HBCI_Transactiong HBCI_Transaction functions */
    /*@{*/
    /** Constructor */
    extern HBCI_Transaction * HBCI_Transaction_new();
    /** Destructor */
    extern void HBCI_Transaction_delete(HBCI_Transaction *t);

    /** @name Our account */
    /*@{*/
    /** country code of your institute -- not in MT940. */
    extern int HBCI_Transaction_ourCountryCode(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setOurCountryCode(HBCI_Transaction *t, int i);

    /** bank code of your institute (BLZ or S.W.I.F.T. code) -- BLZ in
      :25:
      *
      * The const char* pointer of this and all the following
      * functions points to the c_str() result of the underlying
      * std::string object. It is therefore valid as long as the
      * Transaction object wasn't changed, and it should NOT be
      * free'd by the caller.  */
    extern const char * 
    HBCI_Transaction_ourBankCode(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setOurBankCode(HBCI_Transaction *t, const char *code);

    /** Your account number; up to 23 characters. Note: possibly
     * including the currency (yes, that's what MT940 says) --
     * Kontonummer in :25: */
    extern const char * 
    HBCI_Transaction_ourAccountId(const HBCI_Transaction *t);
    extern void 
        HBCI_Transaction_setOurAccountId(HBCI_Transaction *t, const char *id);

    /** If your account has subaccounts which are distinguished by
     * different suffixes, then this is that suffix. Otherwise it's
     * empty. -- not in MT940 */
    extern const char * 
    HBCI_Transaction_ourSuffix(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setOurSuffix(HBCI_Transaction *t, const char *id);
    /*@}*/
    
    /** @name Date */
    /*@{*/
    /** A date "Valuta" when the transaction was (really?) executed --
     * Datum Valuta/Wertstellung in :61: */
    extern const HBCI_Date* 
    HBCI_Transaction_valutaDate(const HBCI_Transaction *t);
    /** 
     * @param t The object to perform this action on.
     * @param d the date. a deep copy of its data will be stored, so the
     * pointer lifecycle doesn't affect this transaction. */
    extern void 
    HBCI_Transaction_setValutaDate(HBCI_Transaction *t, const HBCI_Date *d);

    /** The date when the transaction was booked. In MT940 spec this
     * has only four characters (no year), so we take the year from
     * the valutaDate(HBCI_Transaction *t). -- Buchungsdatum in :61: */
    extern const HBCI_Date* 
    HBCI_Transaction_date(const HBCI_Transaction *t);
    /** 
     * @param t The object to perform this action on.
     * @param d The date. A deep copy of its data will be stored, so the
     * pointer lifecycle doesn't affect this transaction. */
    extern void 
    HBCI_Transaction_setDate(HBCI_Transaction *t, const HBCI_Date *d);
    /*@}*/

    /** @name Value */
    /*@{*/
    /** The value of this transaction in the account's currency. -- Betrag in :61: */
    extern const HBCI_Value* 
    HBCI_Transaction_value(const HBCI_Transaction *t);

    /** 
     * @param t The object to perform this action on.
     * @param v the value. a deep copy of its data will be stored, so the
     * pointer lifecycle doesn't affect this transaction. */
    extern void 
    HBCI_Transaction_setValue(HBCI_Transaction *t, const HBCI_Value *v);
    /*@}*/

    /** @name Type of Transaction */
    /*@{*/
    /** this is the transaction id that tells you more about the type
     * of transaction (3 character code) -- Buchungsschluessel in :61: */
    extern const char * 
    HBCI_Transaction_transactionKey(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setTransactionKey(HBCI_Transaction *t, const char *s);
    /*@}*/

    /** @name Reference String */
    /*@{*/
    /* Reference char *, if the customer (you) has specified
     * one. (E.g. the cheque number.) Otherwise "NONREF". --
     * Kundenreferenz in :61: */
    extern const char * 
    HBCI_Transaction_customerReference(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setCustomerReference(HBCI_Transaction *t, const char *s);
 
    /* Reference char * for this transaction given by the bank, if it
     * has given one. Otherwise empty. -- Bankreferenz in :61: */
    extern const char * 
    HBCI_Transaction_bankReference(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setBankReference(HBCI_Transaction *t, const char *s);
    /*@}*/

    /* Now follows the obnoxious "Mehrzweckfeld :86:" */

    /** @name Transaction Description */
    /*@{*/
    /** A 3 digit numerical transaction code, defined for all kinds of
     * different HBCI actions. -- Geschaeftsvorfallcode, first field
     * in field :86: */
    extern int HBCI_Transaction_transactionCode(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setTransactionCode(HBCI_Transaction *t, int c);

    /** HBCI_Transaction text (e.g. STANDING ORDER); field
     * 00 in field :86: */
    extern const char * 
    HBCI_Transaction_transactionText(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setTransactionText(HBCI_Transaction *t, const char *s);

    /** Primanoten-Number (no idea what this means) --
     * Primanoten-Nummer; field 10 in field :86:  */
    extern const char * 
    HBCI_Transaction_primanota(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setPrimanota(HBCI_Transaction *t, const char *s);

    /** Description of what this transaction is for, and how the Bank
     * describes this transaction.  -- Verwendungszweck; fields 20-29
     * and 60-63 in field :86:  */
    extern const list_string* 
    HBCI_Transaction_description(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_addDescription(HBCI_Transaction *t, const char *s);
    /*@}*/

    /** @name Other account */
    /*@{*/
    /** Country code (BLZ) of the other party's institute -- not in
     * MT940/field :86: */
    extern int 
    HBCI_Transaction_otherCountryCode(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setOtherCountryCode(HBCI_Transaction *t, int i);

    /** Institute code (BLZ);
     * field 30 in field :86: */
    extern const char * 
    HBCI_Transaction_otherBankCode(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setOtherBankCode(HBCI_Transaction *t, const char *s);

    /** Account number of the other party -- Kontonummer; field 31 in
     * field :86: */
    extern const char * 
    HBCI_Transaction_otherAccountId(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setOtherAccountId(HBCI_Transaction *t, const char *s);

    /** If the account of the other party has subaccounts which are
     * distinguished by different suffixes, then this is that suffix
     * of the other party. Otherwise it's empty. -- *not* in MT940 /
     * field :86: */
    extern const char * 
    HBCI_Transaction_otherSuffix(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_setOtherSuffix(HBCI_Transaction *t, const char *id);

    /** Name of the other party -- fields 32 and 33 in field :86: */
    extern const list_string* 
    HBCI_Transaction_otherName(const HBCI_Transaction *t);
    extern void 
    HBCI_Transaction_addOtherName(HBCI_Transaction *t, const char *s);
    /*@}*/

    /** @name List of HBCI_Transaction */
    /*@{*/
    extern void list_HBCI_Transaction_delete(list_HBCI_Transaction *l);
    extern void 
    list_HBCI_Transaction_iter_delete(list_HBCI_Transaction_iter *l);
    extern int list_HBCI_Transaction_size(const list_HBCI_Transaction *l);
    extern list_HBCI_Transaction_iter* 
    list_HBCI_Transaction_begin(const list_HBCI_Transaction *l);
    extern list_HBCI_Transaction_iter* 
    list_HBCI_Transaction_end(const list_HBCI_Transaction *l);
    extern const HBCI_Transaction* 
    list_HBCI_Transaction_iter_get(const list_HBCI_Transaction_iter *l);
    extern void
    list_HBCI_Transaction_iter_next(list_HBCI_Transaction_iter *l);
    extern int 
    list_HBCI_Transaction_iter_equal(const list_HBCI_Transaction_iter *l1, 
				    const list_HBCI_Transaction_iter *l2);
    /** Callback function for @ref list_HBCI_Transaction_foreach . */
    typedef void *(*list_HBCI_Transaction_cb) (const HBCI_Transaction *trans, 
					       void *user_data);
    /** Traverses the list, calling the callback function 'func' on
     * each list element.  Traversal will stop when 'func' returns a
     * non-NULL value, and the routine will return with that
     * value. Otherwise the routine will return NULL. 
     * @param list The list to traverse.
     * @param func The function to be called with each list element.
     * @param user_data A pointer passed on to the function 'func'.
     * @return The non-NULL pointer returned by 'func' as soon as it
     * returns one. Otherwise (i.e. 'func' always returns NULL)
     * returns NULL.
     * @author Christian Stimming <stimming@tuhh.de> */
    extern void *
    list_HBCI_Transaction_foreach (const list_HBCI_Transaction *list, 
				   list_HBCI_Transaction_cb func,
				   void *user_data);
    /*@}*/
    /*@}*/
#ifdef __cplusplus
}

#endif


#endif



