//------------------------------------------------------------------------------
//! @file WiMOD_SAP_LORAWAN_ProLink.h
//! @ingroup WiMOD_SAP_LORAWAN_PROLINK
//! <!------------------------------------------------------------------------->
//! @brief Declarations for the LoRaWAN SericeAccessPoint for ProLink Firmware
//! @version 0.1
//! <!------------------------------------------------------------------------->
//!
//!
//!
//! <!--------------------------------------------------------------------------
//! Copyright (c) 2022
//! IMST GmbH
//! Carl-Friedrich Gauss Str. 2-4
//! 47475 Kamp-Lintfort
//! --------------------------------------------------------------------------->
//! @author (FB), IMST
//! <!--------------------------------------------------------------------------
//! Target OS:    none
//! Target CPU:   tbd
//! Compiler:     tbd
//! --------------------------------------------------------------------------->
//! @internal
//! @par Revision History:
//! <PRE>
//!-----------------------------------------------------------------------------
//! Version | Date       | Author | Comment
//!-----------------------------------------------------------------------------
//!
//! </PRE>
//------------------------------------------------------------------------------


#ifndef ARDUINO_SAP_WIMOD_SAP_LORAWAN_PROLINK_H_
#define ARDUINO_SAP_WIMOD_SAP_LORAWAN_PROLINK_H_

/*
 * THIS IS AN EXAMPLE IMPLEMENTATION ACCORDING THE THE HCI SPEC: V2.0
 * FOR FIRMWARE: ProLink_
 *
 * SEE FILE: ProLink_LoRaWAN_EndNode_Modem_HCI_Spec.pdf (version 2.0)
 * for detailed information
 *
 */


//------------------------------------------------------------------------------
//
// Section Includes Files
//
//------------------------------------------------------------------------------

#include "WiMOD_SAP_LORAWAN.h"
#include "WiMOD_SAP_LORAWAN_ProLink_IDs.h"

/*
 * C++11 supports a better way for function pointers / function objects
 * But C++11 mode is not supported by all platforms.
 */
#ifdef WIMOD_USE_CPP11
#include <functional>
#endif
//------------------------------------------------------------------------------
//
// Section defines
//
//------------------------------------------------------------------------------

/**
 * @brief LoRaWAN Region support
 */
typedef enum TProLinkLoRaWANregion
{
    ProLink_LoRaWAN_Region_EU868,                                               /*!< regional settings for EU 868 MHz  */
    ProLink_LoRaWAN_Region_US915,                                               /*!< regional settings for US 915 MHz  */
    ProLink_LoRaWAN_Region_IN865,                                              /*!< regional settings for India 865 MHz  */
    ProLink_LoRaWAN_Region_AU915,                                               /*!< regional settings for Australia 915 MHz  */
    ProLink_LoRaWAN_Region_AS923,                                               /*!< regional settings for Asia 923 MHz  */
    ProLink_LoRaWAN_Region_RU868,                                               /*!< regional settings for Russia 868 MHz  */

    ProLink_LoRaWAN_Region_proprietary_WW2G4,
} TProLinkLoRaWANregion;



//-----------------------------------------------------------------------------
//
// types for callback functions
//
//-----------------------------------------------------------------------------

// C++11 check
#ifdef WIMOD_USE_CPP11
/* C++11 function callback definitions */

    /** Type definition for a 'reset DevNonce' indication callback  */
    typedef std::function<void (void)> TResetDevNonceIndicationCallback;

    /** Type definition for a 'link disconnect' indication callback  */
    typedef std::function<void (void)> TLinkDisconnectIndicationCallback;

    /** Type definition for a 'network-device-time answer' indication callback  */
    typedef std::function<void (TWiMODLR_HCIMessage& rxMsg)> TNwkDeviceTimeAnsIndicationCallback;

    /** Type definition for a 'Multicast RX Data' indication callback  */
    typedef std::function<void (TWiMODLR_HCIMessage& rxMsg)> TMCastDataIndicationCallback;

    /** Type definition for a 'Multicast RX Invalid Data' indication callback function */
    typedef std::function<void (TWiMODLR_HCIMessage& rxMsg)> TMCastInvalidDataIndicationCallback;

#else
    /* pre C++11 function callback definitions */

    /** Type definition for a 'join tx' indication callback function */
    typedef void (*TResetDevNonceIndicationCallback)(void);

    /** Type definition for a 'link disconnect' indication callback function */
    typedef void (*TLinkDisconnectIndicationCallback)(void);

    /** Type definition for a 'network-device-time answer' indication callback function */
    typedef void (*TNwkDeviceTimeAnsIndicationCallback)(TWiMODLR_HCIMessage& rxMsg);

    /** Type definition for a 'Multicast RX Data' indication callback function */
    typedef void (*TMCastDataIndicationCallback)(TWiMODLR_HCIMessage& rxMsg);

    /** Type definition for a 'Multicast RX Invalid Data' indication callback function */
    typedef void (*TMCastInvalidDataIndicationCallback)(TWiMODLR_HCIMessage& rxMsg);

#endif


//------------------------------------------------------------------------------
//
// Section class
//
//------------------------------------------------------------------------------

/**
 * @brief Implementation for the ServiceAccessPoint LoRaWAN (End Node Modem firmware only)
 */
class WiMOD_SAP_LoRaWAN_ProLink : public WiMOD_SAP_LoRaWAN{
public:

    WiMOD_SAP_LoRaWAN_ProLink(TWiMODLRHCI* hci, UINT8* buffer, UINT16 bufferSize);
    virtual ~WiMOD_SAP_LoRaWAN_ProLink(void);


    virtual void setRegion(TProLinkLoRaWANregion regionalSetting);

    TWiMODLRResultCodes SetDeviceNonce(const UINT16 devNonce, UINT8* statusRsp);
    TWiMODLRResultCodes GetDeviceNonce(UINT16* devNonce, UINT8* statusRsp);

    TWiMODLRResultCodes SetJoinNonce(const UINT16 joinNonce, UINT8* statusRsp);
    TWiMODLRResultCodes GetJoinNonce(UINT16* joinNonce, UINT8* statusRsp);

    TWiMODLRResultCodes SendNwkTimeRequest(TWiMODLORAWAN_DevTimeReqInfo* devTimeInfo, UINT8* statusRsp);

    TWiMODLRResultCodes SendUData(TWiMODProLinkLORAWAN_TX_Data* data, UINT8* statusRsp);
    TWiMODLRResultCodes SendCData(TWiMODProLinkLORAWAN_TX_Data* data, UINT8* statusRsp);


    void               RegisterResetDevNonceIndicationClient(TResetDevNonceIndicationCallback cb);
    void               RegisterLinkDisconnectIndicationClient(TLinkDisconnectIndicationCallback cb);
    void               RegisterDeviceTimeAnsIndicationClient(TNwkDeviceTimeAnsIndicationCallback cb);
    void               RegisterMulticastDataIndicationClient(TMCastDataIndicationCallback cb);
    void               RegisterMulticastInvalidDataIndicationClient(TMCastInvalidDataIndicationCallback cb);


//    TWiMODLRResultCodes   GetLinkAdrReqConfig(TWiMODLORAWAN_LinkAdrReqConfig* linkAdrReqCfg, UINT8* statusRsp);
//    TWiMODLRResultCodes SetLinkAdrReqConfig(TWiMODLORAWAN_LinkAdrReqConfig& linkAdrReqCfg, UINT8* statusRsp);

    TWiMODLRResultCodes SetMulticastConfig(TWiMODLORAWAN_McastConfig& mcastCfg, UINT8* statusRsp);
    TWiMODLRResultCodes GetMulticastConfig(TWiMODLORAWAN_McastConfig* mcastCfg, UINT8* statusRsp);
    TWiMODLRResultCodes RemoveMulticastConfig(const UINT8 mcastIndex, UINT8* statusRsp);

    virtual TWiMODLRResultCodes SetRadioStackConfig(TWiMODProLinkLORAWAN_RadioStackConfig* data, UINT8* statusRsp);
    virtual TWiMODLRResultCodes GetRadioStackConfig(TWiMODProLinkLORAWAN_RadioStackConfig* data, UINT8* statusRsp);


    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_DevTimeAnsInfo*  info);
    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_McastData* mcastData);
    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_McastNoData*  mcastErrData);

//    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_JoinNwkTxIndData* indicationData) {return WiMOD_SAP_LoRaWAN::convert(RxMsg, indicationData); };
    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_RX_Data* loraWanRxData)             {return WiMOD_SAP_LoRaWAN::convert(RxMsg, loraWanRxData); };
//    bool convert(TWiMODLR_HCIMessage& rxMsg, TWiMODLORAWAN_SendDataTxInd_Data* sendIndData)  {return WiMOD_SAP_LoRaWAN::convert(rxMsg, indicationData); };
    bool convert(TWiMODLR_HCIMessage& rxMsg, TWiMODLORAWAN_TxIndData* sendIndData)             {return WiMOD_SAP_LoRaWAN::convert(rxMsg, sendIndData); };
    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_RX_MacCmdData* loraWanMacCmdData)   {return WiMOD_SAP_LoRaWAN::convert(RxMsg, loraWanMacCmdData); };
    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_RX_JoinedNwkData* joinedNwkData)    {return WiMOD_SAP_LoRaWAN::convert(RxMsg, joinedNwkData); };
    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_RX_ACK_Data* ackData)               {return WiMOD_SAP_LoRaWAN::convert(RxMsg, ackData); };
    bool convert(TWiMODLR_HCIMessage& RxMsg, TWiMODLORAWAN_NoData_Data* info)                  {return WiMOD_SAP_LoRaWAN::convert(RxMsg, info); };



    void               DispatchProLinkLoRaWANMessage(TWiMODLR_HCIMessage& rxMsg);
protected:
    //! @cond Doxygen_Suppress
    TResetDevNonceIndicationCallback    ResetDevNonceCallback;
    TLinkDisconnectIndicationCallback   LinkDisconnectCallback;
    TNwkDeviceTimeAnsIndicationCallback DeviceTimeAnsCallback;
    TMCastDataIndicationCallback        MulticastRxDataCallback;
    TMCastInvalidDataIndicationCallback MulticastRxInvalidDataCallback;

    TProLinkLoRaWANregion        ProLink_region;
    //! @endcond
private:
    //! @cond Doxygen_Suppress

    //! @endcond

};


#endif /* ARDUINO_SAP_WIMOD_SAP_LORAWAN_PROLINK_H_ */
