/***************************************************************************
 $RCSfile: swiftparser.h,v $
                             -------------------
    cvs         : $Id: swiftparser.h,v 1.11 2003/09/12 15:02:19 cstim Exp $
    begin       : Sun Aug 05 2001
    copyright   : (C) 2001 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                                                   *
 *                                                                         *
 ***************************************************************************/

/*
 Changes

 */

#ifndef SWIFTPARSER_H
#define SWIFTPARSER_H

#ifdef __cplusplus
#include <string>
#include <list>
#endif /* __cplusplus */

#include <openhbci/date.h>
#include <openhbci/value.h>
#include <openhbci/transaction.h>
#include <openhbci/balance.h>

#ifndef DOXYGEN_HIDE

#ifdef __cplusplus
using namespace std;


namespace HBCI {

/**
 * This is a full transaction report for ONE day.
 * It contains the opening and closing saldo of a day and its transactions.
 * @author Martin Preuss<openhbci@aquamaniac.de>
 */
class DLLIMPORT transactionReport {
    friend class SWIFTParser;
private:
    /** list of transactions */
    list<Transaction> _transactions;
    /** the opening saldo of the day */
    Balance _balanceStart;
    /** the closing saldo of the day */
    Balance _balanceEnd;
    /** default currency */
    string _currency;

public:
    /** list of transactions */
    const list<Transaction>& transactions() const;
    void addTransaction(const Transaction& t);

    /** the opening saldo of the day */
    const Balance &balanceStart() const { return _balanceStart;};
    void setBalanceStart(const Balance &b) { _balanceStart=b;};

    /** the closing saldo of the day */
    const Balance &balanceEnd() const { return _balanceEnd;};
    void setBalanceEnd(const Balance &b) { _balanceEnd=b;};

    /** default currency */
    const string& currency() const { return _currency;};
    void setCurrency(const string &s) { _currency=s;};

    transactionReport(const string& currency="");
    ~transactionReport();
    void dump() const;
};



/**
 * This class is a parser for some SWIFT MT xxx documents.
 * Well, at this time only MT 940 is parsed ;-)
 * @author Martin Preuss<openhbci@aquamaniac.de>
 */
class DLLIMPORT SWIFTparser {
private:

    static string _normalize(const string &s);

    /**
     * Parses a SWIFT MT 940 ":25:" tag.
     * This tag contains our institute code (BLZ) and our id (in most cases
     * this is your account number).
     * Format: ":25:institute_code/account_id"
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return true if successfully parsed, false on error
     * @param tc content of the tag
     * @param instCode reference to a string to receive the institute code
     * @param id reference to a string to receive the account id
     */
    DLLIMPORT static bool _mt940_25(string tc, string &instCode, string &id);

    /**
     * Parses a SWIFT MT 940 ":60X:" or ":62:" tag.
     * This tag contains the opening saldo of a day
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return pointer to the final saldo (0 on error)
     * @param tc content of the tag
     * @param tr reference to a transaction report to receive the balance
     * @param tagId the id of the tag
     */
    DLLIMPORT static bool _mt940_60_62(string tc, transactionReport &tr, string tagId);
    
    /**
     <PRE>
     * Parses a SWIFT MT 940 ":61:" tag.
     * This tag contains data about ONE transaction and my occur multiple times.
     * Format:
     *
     * Description      : Must/: Content (example)  (Additional info)
     *                    Can 
     * -----------------+------+-------------------+----------------------------
     * Tag              : M    : ":61:"
     * Date             : M    : "YYMMDD"           (valuta date)
     * Transaction date : C    : "MMDD"
     * Credit/Debit mark: M    : "C"                (credit) +
     *                           "D"                (debit)  -
     *                           "CR"               (storno credit) +
     *                           "DR"               (storno debit)  -
     * Currency         : C    :                    (3rd part of currency:
     *                                              What the hell do they mean??!
     * Value            : M    :                    (in account's currency)
     * Constant         : M    :  "N"               (dont ask me why ...)  
     * Transaction key  : M    :  "XXX"             (3 character code)     
     * Reference        : M    :  "xxxxxxx"         (e.g. cheque number, or DTA-A field 10)
     *                            "NONREF"          (if there is no reference)
     * Constant         : C    :  "//"              (if bank reference follows)
     * Bank reference   : C    :  "xxxxxxx"         (e.g. field 6b from DTA)
     * Constant         : C    :  <CR><LF> "/"      (if additional info follows)
     * Additional info  : C    :  "/OCMT/EUR100,5/" (original value and currency)
     *                            "/CHGS/EUR22,4/"  (charges)
     * </PRE>
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return true if successfully parsed, false on error
     * @param tc content of the tag
     * @param tda reference to a Transaction struct to store data in
     * @param curr default currency
     */
    DLLIMPORT static bool _mt940_61(string tc, Transaction &tda, string curr);
    
    /**
     * <PRE>
     * Parses a SWIFT MT 940 ":86:" tag.
     * This is a multi field tag containing some additional data.
     * Each field is identified by its number.
     * In the following description "partner" means the other person that
     * is involved in the transaction.
     *
     * Fields:
     * Code     : Description                          Example
     * ---------+-----------------------------------+-------------------------
     * 00       : transaction text                  : "DAUERAUFTRAG" (standing order)
     * 10       : primanota                         : "0599"
     * 20-29    : description                       : "RENT OCTOBER 2001"
     * 30       : partners institute code (BLZ)     : "28250000"
     * 31       : partners account id               : "12345"
     * 32-33    : partners name                     : "JOHN DOE"
     * 34       : dont now, ignored                 :
     * 60-63    : description                       : "WHATEVER YOU LIKE"
     * </PRE>
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @param tc content of the tag
     * @param tda reference to a Transaction struct to store data in
     */
    DLLIMPORT static bool _mt940_86(string tc, Transaction &tda);
    
public:
    /**
     * Returns a string containing the current tag. The string returned
     * includes the trailing <CR> <LF> (end of tag mark).
     * The position of the following tag can be calculated by adding the
     * size of the string returned by this method to the given position (pos)
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return string containing the full tag (possibly empty)
     * @param str the string in which we search
     * @param pos position to start at
     *
     */
    DLLIMPORT static string nextTAG(string str, unsigned int pos);

    /**
     * Returns a string containing the current field. The string returned
     * includes the trailing <CR> <LF> (end of tag mark).
     * The position of the following field can be calculated by adding the
     * size of the string returned by this method to the given position (pos)
     * Fields are sub-structures of tags which occur e.g. in SWIFT MT 940
     * documents (tag ":86:").
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return string containing the full field (possibly empty)
     * @param str the string in which we search
     * @param pos position to start at
     */
    DLLIMPORT static string nextFIELD(string str, unsigned int pos);

    /**
     * Returns the id of the given tag.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return string containing the id (such as "20", "21" etc), possibly empty
     * @param tag tag whose id is to be retrieved
     */
    DLLIMPORT static string tagId(string tag);

    /**
     * Returns the content of the given tag. The trailing "CR,LF" sequence is
     * excluded.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return string containing the tag's content, possibly empty
     * @param tag tag whose content is to be retrieved
     */
    DLLIMPORT static string tagContent(string tag);

    /**
     * Returns the id of the given field.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return numerical id (like 0, 20, etc)
     * @param tag tag whose id is to be retrieved
     */
    DLLIMPORT static int fieldId(string tag, unsigned int &pos);
    DLLIMPORT static int fieldId(string tag);

    /**
     * Returns the content of the given field. IF there is a <CR> <LF> sequence
     * at the end of this field then it will be cut off.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return string containing the field's content, possibly empty
     * @param tag tag whose content is to be retrieved
     */
    DLLIMPORT static string fieldContent(string tag);

    /**
     * Parses a stream of SWIFT MT 940 records and fills the data into a
     * transactionReport. Please note that now ALL transactions go into
     * a single report. In former times this method only parsed ONE single
     * MT940 report (AKA DayReport). Since OpenHBCI stores the single
     * transactions rather than daily reports we now consequently store
     * ALL transactions into one single report.
     * Since some institutes do not comply to the SWIFT standard I had to
     * lighten up the parser. It is now more tolerant.
     * DEVELOPER NOTE: Unknown tags in the record are simply ignored, so if
     * this method reports an error, there might be an error in this method
     * itself !
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return true if the given mt940 record was valid, false on error
     * @param mt940record a string containing a stream of SWIFT MT 940 records
     * @param tr reference to an empty transaction report
     * @param pos the pos to start at when parsing the record. When this method
     * returns pos is positioned to the possible start of the next record
     */
    DLLIMPORT static bool readMT940(string mt940record,
                                    transactionReport &tr,
                                    unsigned int &pos);

};

} /* namespace HBCI */

typedef struct HBCI::transactionReport HBCI_transactionReport;
typedef struct HBCI::SWIFTparser HBCI_SWIFTparser;
extern "C" {
#else /* __cplusplus */
typedef struct HBCI_transactionReport HBCI_transactionReport;
typedef struct HBCI_SWIFTparser HBCI_SWIFTparser;
#endif /* __cplusplus */

  /** @name HBCI_SWIFTparser */
  /*@{*/
  extern int HBCI_SWIFTparser_readMT940(const char *mt940record,
					HBCI_transactionReport *tr,
					unsigned int *pos);

  extern HBCI_transactionReport *HBCI_transactionReport_new();
  extern void HBCI_transactionReport_delete(HBCI_transactionReport *h);

  extern const list_HBCI_Transaction *
  HBCI_transactionReport_transactions(const HBCI_transactionReport *h);

  /** the opening saldo of the day */
  extern const HBCI_Balance *
  HBCI_transactionReport_balanceStart(const HBCI_transactionReport *h);

  /** the closing saldo of the day */
  extern const HBCI_Balance *
  HBCI_transactionReport_balanceEnd(const HBCI_transactionReport *h);

  /** default currency */
  extern const char* 
  HBCI_transactionReport_currency(const HBCI_transactionReport *h);

  /*@}*/
#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* DOXYGEN_HIDE */

#endif
