#ifndef SCPI_CORE_H
#define SCPI_CORE_H
    #include <stdbool.h>
    #include "my_assert.h"
    #include "core/main.h" // _snprintf
    #include "app/fseq/fseq.h"
    #include "app/scpi/scpi_tools.h"
    #include "app/scpi/scpi_base.h" // eScpiStatus_t

    // ==============================================================================================
    // typedef struct
    // {
    //    eScpiStatus_t ( * fInit)();
    //    eScpiStatus_t ( * fWrite)();
    //    eScpiStatus_t ( * fRead)();
    //    eScpiStatus_t ( * fClear)();
    //    eScpiStatus_t ( * fDeInit)();    
    // }
    // sSCPIErrorQueueIface_t;
    // ==============================================================================================
    #define SCPILIB_ERROR_SUCCESS            (0)
    #define SCPILIB_ERROR_BUFFER_OVERFLOW   (-1)
    // ==============================================================================================
    typedef struct
    {
       eScpiStatus_t ( * fInit)( );
       eScpiStatus_t ( * fReset)();
       eScpiStatus_t ( * fNewTransfer)();
       eScpiStatus_t ( * fWrite)( const uint8_t * pData, size_t nDataLen, bool bEndOfMessage, bool bNewTransfer );
       eScpiStatus_t ( * fRead)( uint8_t * pBuffer, size_t nBufferLen, size_t *pnBytesOut, bool *pEOM );
       eScpiStatus_t ( * fNotificationRead)( uint8_t * pBuffer, size_t nBufferLen, size_t *pnBytesOut, uint8_t * pSTB );

       // @fError
       // Error notification from USBTMC level.
       // @error - error id, see @SCPILIB_ERROR_* macro group
       // @errorCtx - error dependent context, optional;
       // Return:
       // - eScpiStatus_success: error processed successfully
       // - eScpiStatus_failed: unrecoveral error, need to process it on USBTMC level.
       eScpiStatus_t ( * fError)( int32_t error, const void * errorCtx );

       eScpiStatus_t ( * fDeInit)();
    }
    sSCPILibHandle_t;   
    // ==============================================================================================
    // @fsq_GetPrivateCtxRef
    // Get access to the state's private context by pointer
    // @this - the state entry, passed into main state function, or 
    // ... entry-/leave- routines.
    // Returns: the state private context pointer that represented by the
    // @ctx_ref field in @sScpiParserStateEntry_t structure.
    void * fsq_GetPrivateCtxRef( const struct fFSeqEntry_t * this );    
    // ==============================================================================================    
    // @fsq_RaiseErrorEx
    // Generate internal error event to place it into SCPI Error Log
    // @scpiError - SCPI error code
    // @msgHandler - optional null-terminated string prefix, if exist, the function also adds additional prefix with error number
    // @msgDescription - optional string message with @msgDescLength length
    // @msgDescriptionEnd - end of optional message string, is used to determine the string length (@msgDescription)
    // @msgDescriptionEx - extended optional string message with @msgDescLength length
    // @msgDescriptionEndEx - end of extended optional message string, is used to determine the string length (@msgDescriptionEx)
    void fsq_RaiseErrorEx( int scpiError, const char * msgHeader, const char * msgDescription, const char * msgDescriptionEnd,
                                                                  const char * msgDescriptionEx, const char * msgDescriptionEndEx );

    // -----------------------------------------------------------
    // @fsq_RaiseError
    // Generate internal error event to place it into SCPI Error Log
    // @scpiError - SCPI error code
    // @msgHandler - optional null-terminated string prefix, if exist, the function also adds additional prefix with error number
    // @msgDescription - optional string message with @msgDescLength length
    // @msgDescriptionEnd - end of optional message string, is used to determine the string length (@msgDescription)
    void fsq_RaiseError( int scpiError, const char * msgHeader, const char * msgDescription, const char * msgDescriptionEnd );

    // -----------------------------------------------------------
    // @scpi_WriteChunkOutput
    // Write data to output buffer
    // @src - pointer to data to be written
    // @length - length of data @src
    // Returns: a number of bytes copied (may be less than @length)
    int32_t scpi_WriteChunkOutput( const void * src, size_t length );

    // @scpi_WriteCharOutput
    // Write a character to output buffer
    // @ch - character to be written    
    // Returns: 1 if a character successfully placed into the buffer, or 0 otherwise
    int32_t scpi_WriteCharOutput( uint8_t ch );
    // -----------------------------------------------------------
    // @scpi_UpdateMessageAvailable
    // Updates the message available status, MAV
    // "6.1.10.2.1 Message Available Message (MAV)", [1]
    void scpi_UpdateMessageAvailable();
    // ==============================================================================================
    extern const sSCPILibHandle_t sSCPILibHandle;
#endif