/***************************************************************************
 * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr
 * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr
 * SPDX-License-Identifier: GPL-3.0-or-later
 ***************************************************************************/
#ifndef SKGOPERATIONOBJECT_H
#define SKGOPERATIONOBJECT_H
/** @file
 * This file defines classes SKGOperationObject.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */

#include "skgbankmodeler_export.h"
#include "skgobjectbase.h"
class SKGAccountObject;
class SKGUnitObject;
class SKGSubOperationObject;
class SKGRecurrentOperationObject;
class SKGPayeeObject;

/**
 * This class manages operation object
 */
class SKGBANKMODELER_EXPORT SKGOperationObject final : public SKGObjectBase
{
public:
    /**
     * This enumerate defines status for operations
     */
    enum OperationStatus {NONE, /**< no status */
                          POINTED, /**< pointed */
                          CHECKED /**< checked */
                         };
    /**
     * This enumerate defines status for operations
     */
    Q_ENUM(OperationStatus)

    /**
    * This enumerate defines the alignment amount mode
    */
    enum AmountAlignmentMode {
        DEFAULT,         /**< Default */
        PROPORTIONAL,    /**< Proportional */
        ADDSUBOPERATION  /**< Add sub operation */
    };
    /**
     * This enumerate defines the alignment amount mode
     */
    Q_ENUM(AmountAlignmentMode)

    /**
     * Default constructor
     */
    explicit SKGOperationObject();

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

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

    /**
     * Copy constructor
     * @param iObject the object to copy
     */

    SKGOperationObject(const SKGOperationObject& iObject);

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

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

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

    /**
     * Duplicate current operation including suboperations and grouped operations
     * @param oOperation the created operation
     * @param iDate date(s) for new operation(s)
     * @param iTemplateMode the template mode for new operation(s)
     * @return an object managing the error.
     *   @see SKGError
     */
    // cppcheck-suppress passedByValue
    SKGError duplicate(SKGOperationObject& oOperation, QDate iDate = QDate::currentDate(), bool iTemplateMode = false) const;

    /**
     * Get the parent account
     * @param oAccount the parent account
     * @return an object managing the error.
     *   @see SKGError
     */
    SKGError getParentAccount(SKGAccountObject& oAccount) const;

    /**
     * Set the parent account
     * @param iAccount the parent account
     * @param iForce force the creation even if the account is closed
     * @return an object managing the error.
     *   @see SKGError
     */
    SKGError setParentAccount(const SKGAccountObject& iAccount, bool iForce = false);

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

    /**
     * Get the number of this operation
     * @return the number
     */
    QString getNumber() const;

    /**
     * Set the mode of operation
     * @param iMode the mode
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError setMode(const QString& iMode);

    /**
     * Get the mode of this operation
     * @return the mode
     */
    QString getMode() const;

    /**
     * Set the payee of operation
     * @param iPayee the payee
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError setPayee(const SKGPayeeObject& iPayee);

    /**
     * Get the payee of this operation
     * @param oPayee the payee
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError getPayee(SKGPayeeObject& oPayee) const;

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

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

    /**
     * Get the status of this operation
     * @return the status
     */
    SKGOperationObject::OperationStatus getStatus() const;

    /**
     * Set the status of operation
     * @param iStatus the status
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError setStatus(SKGOperationObject::OperationStatus iStatus);

    /**
     * Set date of this operation
     * @param iDate the date
     * @param iRefreshSubOperations to refresh the sub operations
     * @return an object managing the error
     *   @see SKGError
     */
    // cppcheck-suppress passedByValue
    SKGError setDate(QDate iDate, bool iRefreshSubOperations = true);

    /**
     * Get date of this operation
     * @return the date
     */
    QDate getDate() const;

    /**
     * Set the unit
     * @param iUnit the unit
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError setUnit(const SKGUnitObject& iUnit);

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

    /**
     * To know if an operation is grouped
     * @return true or false
     */
    bool isInGroup() const;

    /**
     * To know if the current operation is a transfer of the other one
     * @param oOperation the other operation
     * @return true or false
     */
    bool isTransfer(SKGOperationObject& oOperation) const;

    /**
     * Set the group operation
     * @param iOperation the operation (itself to remove from group)
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError setGroupOperation(const SKGOperationObject& iOperation);

    /**
     * Get the group operation
     * @param oOperation the operation
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError getGroupOperation(SKGOperationObject& oOperation) const;

    /**
     * Get all operations in the same group
     * @param oGroupedOperations all operation in the same group
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError getGroupedOperations(SKGListSKGObjectBase& oGroupedOperations) const;

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

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

    /**
     * To set the imported attribute of an operation
     * @param iImported the imported status: true or false
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError setImported(bool iImported);

    /**
     * To know if the operation has been imported or not
     * @return an object managing the error
     *   @see SKGError
     */
    bool isImported() const;

    /**
     * Set the import identifier of operation, t_imported is set to 'T'
     * @param iImportID the import identifier (it is used to check if the operation is already imported)
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError setImportID(const QString& iImportID);

    /**
     * Get the import identifier of operation
     * @return the comment
     */
    QString getImportID() const;

    /**
     * To set the template attribute of an operation
     * @param iTemplate the template status: true or false
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError setTemplate(bool iTemplate);

    /**
     * To know if the operation is a template or not
     * @return an object managing the error
     *   @see SKGError
     */
    bool isTemplate() const;

    /**
     * Add a new suboperation to this operation
     * @param oSubOperation the created suboperation
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError addSubOperation(SKGSubOperationObject& oSubOperation);

    /**
     * Get the number of sub operations
     * @return number of sub operations
     */
    int getNbSubOperations() const;

    /**
     * Get all suboperations of this operation
     * @param oSubOperations all suboperations of this operation
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError getSubOperations(SKGListSKGObjectBase& oSubOperations) const;

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

    /**
     * Get the account balance for this operation
     * @return the account balance
     */
    double getBalance() const;

    /**
     * Get amount of the operation at a date
     * @param iDate date
     * @return amount of the operation
     */
    // cppcheck-suppress passedByValue
    double getAmount(QDate iDate) const;

    /**
     * Create a recurrent operation based on this one
     * @param oRecurrentOperation the created recurrent operation
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError addRecurrentOperation(SKGRecurrentOperationObject& oRecurrentOperation) const;

    /**
     * Get the recurrent operations based on this one
     * @param oRecurrentOperation the recurrent operations
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError getRecurrentOperations(SKGListSKGObjectBase& oRecurrentOperation) const;

    /**
     * Merge current operation with another one
     * @param iDeletedOne after merge this operation will be deleted
     * @param iMode the alignment mode
     * @param iSendMessage send warning message
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError mergeAttribute(const SKGOperationObject& iDeletedOne, SKGOperationObject::AmountAlignmentMode iMode = SKGOperationObject::DEFAULT, bool iSendMessage = true);

    /**
     * Merge current operation with another one
     * @param iDeletedOne after merge this operation will be deleted
     * @return an object managing the error
     *   @see SKGError
     */
    SKGError mergeSuboperations(const SKGOperationObject& iDeletedOne);
};
/**
 * Declare the class
 */
Q_DECLARE_TYPEINFO(SKGOperationObject, Q_MOVABLE_TYPE);
#endif
