/*****************************************************************************/
/*
 * Import header for StreamParser version 1.1
 * 
 * Manufacturer
 * 
 *    SCANLAB GmbH
 *    Siemensstr. 2a
 *    82178 Puchheim
 *    Germany
 * 
 *    Tel. + 49 (89) 800 746-0
 *    Fax: + 49 (89) 800 746-199
 * 
 *    info@scanlab.de
 *    www.scanlab.de
 * 
 */
/*****************************************************************************/

#ifndef STREAM_PARSER_C_HEADER
#define STREAM_PARSER_C_HEADER

#include "StreamParser_Export.h"
#ifdef __cplusplus
    #include <cstdint>
extern "C" {
#else
    #include <stdbool.h>
    #include <stdint.h>
#endif

/*! Structure holding version information.
*/
struct slsp_version_info
{
    uint32_t Major;
    uint32_t Minor;
    uint32_t Patch;
};
typedef struct slsp_version_info slsp_version_info;

/*! Structure holding meta data send with every data package by the RTC6 Ethernet card.
* 
*  The values were recorded at a random time during the recording of the package.
* 
*/
struct slsp_rtc_meta_data
{
    uint32_t Period;           //!< Reference set_trigger
    uint64_t TimeStamp;        //!< Reference get_timestamp_long
    uint32_t SerialNumber;     //!< Reference get_serial_number
    uint32_t OUTVersion;       //!< Reference get_hex_version
    uint32_t RBFVersion;       //!< Reference get_rtc_version
    uint32_t BiosVersion;      //!< Reference get_bios_version
    uint32_t ListBusy;         //!< Reference get_status
    uint32_t OutputPointer;    //!< Reference get_out_pointer
    uint32_t ExtStartCounter;  //!< Reference get_counts
    uint32_t OverrunCounter;   //!< Reference get_overrun
    uint32_t McBSPIn;          //!< Reference get_mcbsp
    double Laptime;            //!< Reference get_lap_time
    double Timer;              //!< Reference get_time
    uint32_t WaitStatus;       //!< Reference get_wait_status
    uint32_t FlyOffsetX;       //!< Reference get_fly_2d_offset
    uint32_t FlyOffsetY;       //!< Reference get_fly_2d_offset
    uint16_t ListStartCounter; //!< Reference set_trigger Signal 67, Bit 0...3
    uint16_t ListStopCounter;  //!< Reference set_trigger Signal 67, Bit 4...7
    uint32_t MasterIP;         //!< Reference eth_get_card_info Byte 6
    uint32_t HeadStatus;       //!< Reference get_head_status
};
typedef struct slsp_rtc_meta_data slsp_rtc_meta_data;

/*! Proxy for internal stream parser instance.
*/
struct slsp_stream_parser;
typedef struct slsp_stream_parser slsp_stream_parser;

/*! Proxy for data stream. 
* Used as input for the slsp_data_stream_... API functions.
* A data stream contains all collected data packages since the last call of the callback function.
* A data stream can be queried for number of data packages and each data package can be retrieved.
*/
struct slsp_rtc_data_stream;
typedef struct slsp_rtc_data_stream slsp_rtc_data_stream;

/*! Proxy for data package.
* Used as input for the slsp_data_package_... API functions.
* A data point can be queried for channel count, meta data and waveform data for each channel.
*/
struct slsp_rtc_data_package;
typedef struct slsp_rtc_data_package slsp_rtc_data_package;

/*! Callback function type.
* Takes pointers to an instance of stream parser and a user defined context.
* It is called regularly after a certain number of data packages was accumulated in the data stream. 
* The internal data stream to which the parameter Stream refers is cleared after this function returns. 
* Do not delete *stream. Use only within this callback.
*/
typedef void (*slsp_stream_callback)(slsp_rtc_data_stream* stream, void* context);

/*! State of stream associated with a particular stream parser.
*/
enum slsp_stream_parser_state
{
    slsp_STREAM_CONNECTED = 0,       /*!< TCP client is connected and ready to receive data. */
    slsp_STREAM_RECEIVING = 1,       /*!< Stream is currently running, i.e. data packages are received from RTC6 Ethernet card and the callback function is called repeatedly. */
    slsp_STREAM_DISCONNECTED = 2,    /*!< Stream has finished properly, because the RTC6 Ethernet card has stopped sending data packages or disconnect request has been sent. */
    slsp_STREAM_STOPPED_ON_ERROR = 3 /*!< Stream has stopped, because an error has occurred.*/
};
typedef enum slsp_stream_parser_state slsp_stream_parser_state;

/*! Error code returned by the API functions.
*/
enum slsp_stream_parser_error_code
{
    slsp_error_code_OK = 0,                          /*!< API function succeeded. No error.*/
    slsp_error_code_ESTABLISH_CONNECTION_FAILED = 1, /*!< API function failed. Connection to RTC6 Ethernet card could not be established.*/
    slsp_error_code_RECEIVE_PACKAGE_FAILED = 2,      /*!< API function failed. Error while trying to receive a data package from RTC6 Ethernet card.*/
    slsp_error_code_UNKNOWN_ERROR = 3,               /*!< API function failed. An unspecified error has occurred.*/
    slsp_error_code_RTC_VERSION_ERROR = 4            /*!< API function failed. The version of the connected RTC is not compatible with this stream parser version.*/
};
typedef enum slsp_stream_parser_error_code slsp_stream_parser_error_code;

/*! Returns the API version (major.minor.patch)
*
* The API is versioned according to Semantic Versioning (https://semver.org/).
* 
* @returns Returns a slsp_VersionInfo struct that incorporates the major, minor and patch number.
*/
DLLAPI slsp_version_info slsp_get_version_info(void);

/*! Creates a new stream parser instance and returns a pointer to it.
* 
* The data streaming starts not on creation of the stream parser instance but with slsp_stream_parser_connect.
* Ownership of the object slsp_stream_parser is transferred to the caller via an raw c pointer.
* The caller needs to make sure to delete the object at the end of its usage with slsp_stream_parser_delete. 
* During a streaming session, the user defined slsp_stream_callback is called repeatedly. A pointer to the DataPackage 
* is then passed to the slsp_stream_callback for user defined processing.
* It is recommended to only copy the content of a slsp_rtc_data_package inside the slsp_stream_callback and process the data in an extra thread.
* 
* @param ipaddress IP address of the RTC6 Ethernet card to connect with.
* @param callback Pointer to user defined callback function for stream data processing.
* @param context Pointer to user defined context parameter of callback function.
* @param code Error code returned by API function.
* @return Returns a pointer to a stream parser instance.
*/
DLLAPI slsp_stream_parser* slsp_stream_parser_create(const char* ipaddress,
                                                     slsp_stream_callback callback,
                                                     void* context,
                                                     slsp_stream_parser_error_code* code);

/*! Returns state of the stream associated with a particular stream parser instance.
* 
* @param parser Pointer to a stream parser instance returned by slsp_stream_parser_create.
* @param code Error code returned by API function.
* @return Returns state information of the stream.
*/
DLLAPI slsp_stream_parser_state slsp_stream_parser_get_state(const slsp_stream_parser* parser,
                                                             slsp_stream_parser_error_code* code);

/*! Starts the streaming session by establishing a connection to the TCP server. 
* 
* @param parser Pointer to a stream parser instance returned by slsp_stream_parser_create.
* @param code Error code returned by API function.
 */
DLLAPI void slsp_stream_parser_connect(const slsp_stream_parser* parser, slsp_stream_parser_error_code* code);

/*! Ends the streaming session by disconnecting from the TCP server.
* 
* @param parser Pointer to a stream parser instance returned by slsp_stream_parser_create.
* @param code Error code returned by API function.
 */
DLLAPI void slsp_stream_parser_disconnect(const slsp_stream_parser* parser, slsp_stream_parser_error_code* code);

/*! Checks if the streaming session is established.
 *
 * @param parser Pointer to a stream parser instance returned by slsp_stream_parser_create.
 * @param code Error code returned by API function.
 */
DLLAPI bool slsp_stream_parser_is_connected(const slsp_stream_parser* parser, slsp_stream_parser_error_code* code);

/*! Returns the error message if any error has happened in the extra thread of the associated streaming session.
* 
* @param parser Pointer to a stream parser instance returned by slsp_stream_parser_create.
* @param code Error code returned by API function.
 */
DLLAPI void slsp_stream_parser_get_async_error(const slsp_stream_parser* parser, slsp_stream_parser_error_code* code);

/*! Changes the default value of TCP connection timeout. (default = 10s)
* 
* @param parser Pointer to a stream parser instance returned by slsp_stream_parser_create.
* @param Seconds (Note: if Seconds == 0s; the StreamParser autmotically sets Seconds to 1s)
* @param code Error code returned by API function.
 */
DLLAPI void slsp_stream_parser_set_tcp_timeout(const slsp_stream_parser* parser, uint32_t Seconds, slsp_stream_parser_error_code* code);


/*! Changes the default number of packages, which are passed to the callback handler.
* Call this before calling <connect>"()"
* @param new_package_counter Number of packages for the callback handler. For new_package_counter = 0 the default value = 25 is used.
 */
DLLAPI void slsp_stream_parser_set_package_counter(const slsp_stream_parser* parser, uint32_t new_package_counter, slsp_stream_parser_error_code* code);

/*! Sets the time period for the periodic timer, which reads the current stream and triggers the callback handler.
* Call this before calling <connect>"()"
* @param new_wait_time_ms Time period for the periodic triggering of the callback handler. For new_wait_time_ms = 0 the default value = 250 ms is used.
 */
DLLAPI void slsp_stream_parser_set_wait_time_ms(const slsp_stream_parser* parser, uint32_t new_wait_time_ms, slsp_stream_parser_error_code* code);


/*! Destroys the specified stream parser instance.
* 
* The data streaming stops on destruction of the stream parser instance, if it was not properly 
* stopped by the RTC6 Ethernet card or a network communication error before.
* The data streaming can also be stopped with slsp_stream_parser_disconnect.
* 
* @param parser Pointer to a stream parser instance returned by slsp_stream_parser_create.
* @param code Error code returned by API function.
*/
DLLAPI void slsp_stream_parser_delete(slsp_stream_parser* parser,
                                      slsp_stream_parser_error_code* code);

/*! Returns the number of available data packages.
* 
* The size is reduced with each call to slsp_rtc_data_stream_pop by 1. 
* 
* @param parser Pointer to a data stream object supplied by callback.
* @param code Error code returned by API function.
* @return Returns the number of available data packages.
*/
DLLAPI size_t slsp_rtc_data_stream_get_size(const slsp_rtc_data_stream* stream,
                                            slsp_stream_parser_error_code* code);

/*! Retrieves a data package from data stream.
* 
* The ownership of the slsp_rtc_data_package is transferred the caller and needs to be deleted at the end of its usage with slsp_rtc_data_package_delete.
* 
* @param parser Pointer to a data stream object supplied by callback.
* @param code Error code returned by API function.
* @return Returns pointer to the copied data stream.
*/
DLLAPI slsp_rtc_data_package* slsp_rtc_data_stream_pop(slsp_rtc_data_stream* stream,
                                                       slsp_stream_parser_error_code* code);

/*! Returns the meta data associated with a particular data point.
*
* The meta data is send with every RTC6 Ethernet data package. 
* Its update frequency therefore depends on the configuration of the RTC6 Ethernet board.
* 
* @param package Pointer to data package.
* @param code Error code returned by API function.
* @return Returns the meta data of the data package.
*/
DLLAPI slsp_rtc_meta_data slsp_rtc_data_package_get_meta_data(const slsp_rtc_data_package* package,
                                                              slsp_stream_parser_error_code* code);

/*! Returns the number of channels associated with a data package.
*
* The number of channels depends on the configuration of the RTC6 Ethernet board, 
* in particular which kind of set_trigger command was used.
* 
* @param package Pointer to data package.
* @param code Error code returned by API function.
* @return Returns number of channels of a particular slsp_DataPoint object.
*/
DLLAPI uint32_t slsp_rtc_data_package_get_channel_count(const slsp_rtc_data_package* package,
                                                        slsp_stream_parser_error_code* code);

/*! Returns the waveform data for one channel.
* 
* This functions copys the waveform into a user supplied array. 
* 
* @param package Pointer to data package.
* @param waveform_data User has to supply an array of size slsp_rtc_data_package_get_size
* @param waveform_data Size of waveform_data
* @param channel Channel number to query for signal.
* @param code Error code returned by API function.
* @return Returns the size of copied values.
*/
DLLAPI size_t slsp_rtc_data_package_get_waveform(const slsp_rtc_data_package* package,
                                                 int32_t* waveform_data,
                                                 size_t waveform_data_size,
                                                 uint32_t channel,
                                                 slsp_stream_parser_error_code* code);

/*! Returns the number of data points in a particular data package.
* 
* The number of data points correspond to the setting in 
* n_eth_config_waveform_streaming of RTC6 Ethernet board.
* 
* @param package Pointer to data package.
* @param code Error code returned by API function.
* @return Returns number of data points of a particular data stream.
*/
DLLAPI size_t slsp_rtc_data_package_get_size(const slsp_rtc_data_package* package,
                                             slsp_stream_parser_error_code* code);

/*! Returns the channel type.
* 
* Reference set_trigger/set_trigger4.
* 
* @param package Pointer to data package.
* @param Channel number to query for type 
*        Must be smaller than the value returned by slsp_rtc_data_package_get_channel_count.
* @param code Error code returned by API function.
* @return Returns the channel type set with set_trigger.
*/
DLLAPI uint32_t slsp_rtc_data_package_get_waveform_type(const slsp_rtc_data_package* package,
                                                        size_t channel,
                                                        slsp_stream_parser_error_code* code);

/*! Destroys the data package.
* 
* This needs to be called for each slsp_rtc_data_package that was retrieved by slsp_rtc_data_stream_pop.
* 
* @param parser Pointer to a data package object returned by slsp_rtc_data_stream_pop.
* @param code Error code returned by API function.
*/
DLLAPI void slsp_rtc_data_package_delete(slsp_rtc_data_package* package,
                                         slsp_stream_parser_error_code* code);



#ifdef __cplusplus
}
#endif

#endif // STREAM_PARSER_C_HEADER
