#pragma once

/// @file
/// @brief Define API functions for the Business Mail envelopes
///
/// @copyright Copyright 2021 InfoTeCS.

#include <stdint.h>
#include <stddef.h>
#include <time.h>

#if ( __GNUC__ >= 4 ) || defined( __clang__ )
#   define BmApiExport __attribute__( ( visibility( "default" ) ) )
#else
#   define BmApiExport
#endif

enum BusinessMailApiVersion
{
    BUSINESS_MAIL_API_VERSION = 1
};

/// @brief Envelope type
enum VpnBusinessMailEnvelopeType
{
    BmLetter = 0, ///> Message
    BmReceipt = 1 ///> Receipt
};

/// @brief Message recipient type
enum VpnBusinessMailRecipientType
{
    BmRecipientTo = 0,    ///> The "To" recipient
    BmRecipientCopy = 1,  ///> The "Copy" recipient
    BmRecipientHidden = 2 ///> The "CC" recipient
};

/// @brief Command execution result
typedef struct
{
    /// @brief Function output code (0 - success)
    uint32_t code;

    /// @brief Error message (blank if success)
    /// @remarks Does not require the memory release. The message is stored till the next command call.
    const char* message;
} BusinessMailApiReturnCode;

///@brief Business Mail message details
typedef struct
{
    uint32_t sender;        ///> Sender host ID
    uint32_t* recipientIds; ///> IDs of all the recipient hosts (for an incoming message, the current recipient is the first in the list)
    enum VpnBusinessMailRecipientType* recipientTypes; ///> Recipient type
    size_t recipientsCount;                            ///> Recipient count
    const char* regNumber;                             ///> Message registration number
    const char* subject;                               ///> Message subject
    const char* message;                               ///> Message
    time_t creationTime;                               ///> Creation date
    time_t sendTime;                                   ///> Send date
    const char** attachmentPaths;                      ///> Attachment paths
    const char** attachmentNames;                      ///> Attachment names
    size_t attachmentsCount;                           ///> Atachment count
} VpnBusinessMailLetterData;

///@brief Business Mail receipt details
typedef struct
{
    uint32_t sender;        ///> Sender host ID
    uint32_t recipient;     ///> Recipient host ID
    uint8_t type;           ///> Receipt type
    const char* letterName; ///> Message envelope name
    time_t creationTime;    ///> Creation date
} VpnBusinessMailReceiptData;

/// @brief Get the Business Mail envelope list
/// @param[in] type - envelope type
/// @param[out] envelopes - envelope list
/// @param[out] size - envelope count
/// @remarks The envelopes memory is allocated dynamically and must be released manually
/// @return Command execution result
typedef BusinessMailApiReturnCode ( *GetBusinessMailEnvelopes )( enum VpnBusinessMailEnvelopeType type,
                                                                 char*** envelopes,
                                                                 size_t* size );

/// @brief Delete the Business Mail envelope
/// @param[in] envelope - envelope name
/// @return Command execution result
typedef BusinessMailApiReturnCode ( *RemoveBusinessMailEnvelope )( const char* envelope );

/// @brief Unpack the Business Mail message
/// @param[in] envelope - envelope name
/// @param[in] attachmentsDir - directory to copy the attachments, if any
/// @param[out] bmData - message envelope contents
/// @remarks The bmData memory is allocated dynamically and must be released using ReleaseVpnBusinessMailLetterData( bmData )
/// @return Command execution result
typedef BusinessMailApiReturnCode ( *UnpackBusinessMailLetter )( const char* envelope,
                                                                 const char* attachmentsDir,
                                                                 VpnBusinessMailLetterData** bmData );

/// @brief Unpack the Business Mail receipt
/// @param[in] envelope - receipt envelope name
/// @param[out] bmData - receipt contents
/// @remarks The bmData memory is allocated dynamically and must be released using ReleaseVpnBusinessMailReceiptData( bmData )
/// @return Command execution result
typedef BusinessMailApiReturnCode ( *UnpackBusinessMailReceipt )( const char* envelope,
                                                                  VpnBusinessMailReceiptData** bmData );

/// @brief Create and send the Business Mail message
/// @param[in] bmData - message envelope contents
/// @param[out] envelopes - envelope names (sorted in order of recipients)
/// @param[out] size - envelope count
/// @remarks The envelopes memory is allocated dynamically and must be released manually
/// @return Command execution result
typedef BusinessMailApiReturnCode ( *PackBusinessMailLetter )( VpnBusinessMailLetterData* bmData,
                                                               char*** envelopes,
                                                               size_t* size );

/// @brief Generate and send the Business Mail receipt
/// @param[in] bmData - receipt envelope contents
/// @param[out] envelope - envelope name
/// @remarks The envelope memory is allocated dynamically and must be released manually
/// @return Command execution result
typedef BusinessMailApiReturnCode ( *PackBusinessMailReceipt )( VpnBusinessMailReceiptData* bmData, char** envelope );

/// @brief Release memory allocated to the message contents
/// @param[in] bmData - message envelope contents
/// @return Command execution result
typedef BusinessMailApiReturnCode ( *ReleaseVpnBusinessMailLetterData )( VpnBusinessMailLetterData* bmData );

/// @brief Release memory allocated to the receipt contents
/// @param[in] bmData - receipt envelope contents
/// @return Command execution result
typedef BusinessMailApiReturnCode ( *ReleaseVpnBusinessMailReceiptData )( VpnBusinessMailReceiptData* bmData );

/// @brief API functions for Business Mail envelopes (described above)
typedef struct
{
    // API_VERSION_1
    GetBusinessMailEnvelopes getBusinessMailEnvelopes;
    RemoveBusinessMailEnvelope removeBusinessMailEnvelope;
    UnpackBusinessMailLetter unpackBusinessMailLetter;
    UnpackBusinessMailReceipt unpackBusinessMailReceipt;
    PackBusinessMailLetter packBusinessMailLetter;
    PackBusinessMailReceipt packBusinessMailReceipt;
    ReleaseVpnBusinessMailLetterData releaseVpnBusinessMailLetterData;
    ReleaseVpnBusinessMailReceiptData releaseVpnBusinessMailReceiptData;
} ItcsBusinessMailApi;

#ifdef __cplusplus
extern "C" {
#endif

/// @brief Get the current version of API for Business Mail envelopes
/// @remarks When updating API, check it for compatibility; otherwise, correct operation is not guaranteed
/// @return Current version of API for Business Mail envelopes
BmApiExport uint32_t GetBusinessMailApiVersion();

/// @brief Get the pointer to the structure of API for Business Mail envelopes
/// @return Pointer to the structure of API for Business Mail envelopes
BmApiExport ItcsBusinessMailApi* GetBusinessMailApi();

#ifdef __cplusplus
}
#endif
