/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
#ifndef SKGACCOUNTOBJECT_H
#define SKGACCOUNTOBJECT_H
/** @file
 * This file defines classes SKGAccountObject.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */

#include "skgnamedobject.h"
#include "skgbankmodeler_export.h"
class SKGBankObject;
class SKGOperationObject;
class SKGDocumentBank;
class SKGUnitObject;
class SKGInterestObject;

/**
 * This class manages account object
 */
class SKGBANKMODELER_EXPORT SKGAccountObject : public SKGNamedObject
{
    Q_OBJECT;
    /**
     * This enumerate defines type of account
     */
    Q_ENUMS(AccountType);
public:
    /**
     * Describe a interest item
     */
    struct SKGInterestItem {
        SKGObjectBase object;   /**< The object (an operation, an interest or nothing for initial balance) */
        QDate date;             /**< The date */
        QDate valueDate;    /**< The valueDate */
        int base;           /**< Base */
        double amount;          /**< Amount */
        double coef;            /**< Coef */
        double rate;            /**< Rate */
        double annualInterest;  /**< Annual Interest */
        double accruedInterest; /**< Accrued Interest */
    } ;

    /**
     * This enumerate defines type of account
     */
    enum AccountType {CURRENT,   /**< to define a bank account*/
                      CREDITCARD,/**< to define a credit card account*/
                      INVESTMENT,/**< to define an account for investment */
                      ASSETS,    /**< to define a assets account */
                      OTHER,     /**< other kind of account */
                      WALLET,    /**< to define a wallet account */
                      LOAN,       /**< to define a loan account */
                      SAVING       /**< to define a saving account */
                     };

    /**
     * Constructor
     * @param iDocument the document containing the object
     * @param iID the identifier in @p iTable of the object
     */
    explicit SKGAccountObject(SKGDocument* iDocument = NULL, int iID = 0);

    /**
     * Copy constructor
     * @param iObject the object to copy
     */
    SKGAccountObject(const SKGAccountObject& iObject);

    /**
     * Copy constructor
     * @param iObject the object to copy
     */
    SKGAccountObject(const SKGNamedObject& iObject);

    /**
     * Copy constructor
     * @param iObject the object to copy
     */
    SKGAccountObject(const SKGObjectBase& iObject);

    /**
     * Operator affectation
     * @param iObject the object to copy
     */
    virtual const SKGAccountObject& operator= (const SKGObjectBase& iObject);

    /**
     * Destructor
     */
    virtual ~SKGAccountObject();

    /**
     * Get the parent bank
     * @param oBank the parent bank
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError getBank(SKGBankObject& oBank) const;

    /**
     * Set the parent bank
     * @param iBank the parent bank
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError setBank(const SKGBankObject& iBank);

    /**
     * Set the initial balance of this account
     * @param iBalance the balance
     * @param iUnit the unit
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError setInitialBalance(double iBalance, const SKGUnitObject& iUnit);

    /**
     * Get the initial balance of this account
     * @param oBalance the balance
     * @param oUnit the unit
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError getInitialBalance(double& oBalance, SKGUnitObject& oUnit);

    /**
     * Set the number of the account
     * @param iNumber the number
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError setNumber(const QString& iNumber);

    /**
     * Get the number of the account
     * @return the number
     */
    virtual QString getNumber() const;

    /**
     * Set the agency number of the account
     * @param iNumber the agency number
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError setAgencyNumber(const QString& iNumber);

    /**
     * Get the agency number of the account
     * @return the number
     */
    virtual QString getAgencyNumber() const;

    /**
     * Set the agency address of the account
     * @param iAddress the agency address
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError setAgencyAddress(const QString& iAddress);

    /**
     * Get the agency address of the account
     * @return the number
     */
    virtual QString getAgencyAddress() const;

    /**
     * Set the comment of account
     * @param iComment the comment
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError setComment(const QString& iComment);

    /**
     * Get the comment of this account
     * @return the comment
     */
    virtual QString getComment() const;

    /**
     * Add a new operation to this account
     * @param oOperation the created operation
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError addOperation(SKGOperationObject& oOperation);

    /**
     * Get number of operations
     * @return the number of operations
     */
    virtual int getNbOperation() const;

    /**
     * Get all operations of this account
     * @param oOperations all operations of this account
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError getOperations(SKGListSKGObjectBase& oOperations) const;

    /**
     * Get the current amount
     * @return the current amount
     */
    virtual double getCurrentAmount() const;

    /**
     * Get amount of the account at a date
     * @param iDate date
     * @return amount of the account
     */
    virtual double getAmount(const QDate& iDate) const;

    /**
     * Set the type of this account
     * @param iType the type
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError setType(SKGAccountObject::AccountType iType);

    /**
     * Get the type of this account
     * @return the type
     */
    virtual SKGAccountObject::AccountType getType() const;

    /**
     * To set the closed attribute of an account
     * @param iClosed the closed attribute: true or false
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError setClosed(bool iClosed);

    /**
     * To know if the account has been closed or not
     * @return an object managing the error
     *   @see SKGError
     */
    virtual bool isClosed() const;

    /**
     * To bookmark or not an account
     * @param iBookmark the bookmark: true or false
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError bookmark(bool iBookmark);

    /**
     * To know if the account is bookmarked
     * @return an object managing the error
     *   @see SKGError
     */
    virtual bool isBookmarked() const;

    /**
     * Get the unit
     * @param oUnit the unit
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError getUnit(SKGUnitObject& oUnit) const;

    /**
     * Add an interest
     * @param oInterest the created interest
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError addInterest(SKGInterestObject& oInterest);

    /**
     * Get interests
     * @param oInterestList the list of interest in this account
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError getInterests(SKGListSKGObjectBase& oInterestList) const;

    /**
     * Get interest object at a given date
     * @param iDate the date
     * @param oInterest the interest object
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError getInterest(const QDate& iDate, SKGInterestObject& oInterest) const;

    /**
     * Get and compute interest items
     * @param oInterestList interest items
     * @param oInterests sum of annual interests
     * @param iYear the year of computation (default=current year)
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError getInterestItems(QList<SKGAccountObject::SKGInterestItem>& oInterestList, double& oInterests, int iYear = 0) const;

    /**
     * Compute all items
     * @param ioInterestList interest items
     * @param oInterests sum of annual interests
     * @param iYear the year of computation (default=current year)
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError computeInterestItems(QList<SKGAccountObject::SKGInterestItem>& ioInterestList, double& oInterests, int iYear = 0) const;

    /**
     * Try to point all imported operations to obtain the expected balance
     * @param iBalance the expected balance in the account unit
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError autoReconcile(double iBalance);

    /**
     * Merge iAccount in current account
     * @param iAccount the account. All operations will be transferred into this account. The account will be removed
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError merge(const SKGAccountObject& iAccount);
};
/**
 * Declare the class
 */
Q_DECLARE_TYPEINFO(SKGAccountObject, Q_MOVABLE_TYPE);
/**
  * Declare the class
  */
Q_DECLARE_TYPEINFO(SKGAccountObject::SKGInterestItem, Q_PRIMITIVE_TYPE);
#endif
