/*
 * Copyright (C) 2022 EXOLIGENT (www.exoligent.com)
 * Author: Maxime Coroyer <maxime.coroyer@exoligent.com>
 */

#ifndef __COMMON_H__
#define __COMMON_H__

#if defined(__QNX__)
#   include <sys/syspage.h> // SYSPAGE_ENTRY
#endif

#if defined (_WIN32) || defined (_WIN64)
#   include <windows.h>
/* Some MinGW/CYGWIN distributions don't define the macro: */
#   ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#       define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#   endif
#endif

#include <stdio.h>
#include <sys/time.h>   // gettimeofday(), timeval
#include <stdint.h>     // uint8_t, ...
#include <inttypes.h>   // PRIx64
#include <stdbool.h>    // bool

extern int running;
extern bool dbg_coloriz;

/****************************************************************************************
 * STATISTICS
 ***************************************************************************************/
extern void update_min_max(uint64_t current_value, uint64_t *min_value,
            uint64_t *max_value);
extern int _usleep(uint32_t usec);
#if defined(__QNX__) || defined(_WIN32) || defined(_WIN64)
extern int _gettime(uint64_t *when);
extern void update_stats(uint64_t *start, uint64_t *stop, uint64_t *cp,
    uint64_t *cumul, uint64_t *min, uint64_t *max);
#else
extern int _gettime(struct timeval *when);
extern void update_stats(struct timeval *start, struct timeval *stop,
    uint64_t *cp, uint64_t *cumul, uint64_t *min, uint64_t *max);
#endif

/****************************************************************************************
 * TIME/DATE FUNCTIONS
 ***************************************************************************************/
#define DBG_PRINT_INFO 1
#define DBG_PRINT_WARN 1
#define DBG_PRINT_ERR  1
#define DBG_PRINT_EVT  1
#define DBG_DUMP_MEM   0
#define DGB_COLORIZ    1

typedef enum
{
    fip = 0,    // fip
    mbus,       // modbus
    app,        // application (general)
    no_src      // unknown
} msg_src;

typedef enum
{
    info = 0,   // information
    warn,       // warning
    err,        // error
    evt,        // event (callback)
    no_type     // unknown
} msg_type;

extern char *get_date();
extern struct timespec timespec_diff(struct timespec start, struct timespec end);
extern struct timespec timespec_add_ns(struct timespec ref, long ns);
extern bool b_then_a(struct timespec a, struct timespec b);

#if defined(__QNX__)
extern uint64_t clock_diff_ns(uint64_t start_clk_cycl, uint64_t end_clk_cycl);
#endif

#if defined(__QNX__) || defined(_WIN32) || defined(_WIN64)
extern unsigned long get_elapsed_us(uint64_t end, uint64_t start);
#else
extern unsigned long get_elapsed_us(struct timeval end, struct timeval start);
#endif

/****************************************************************************************
 * CUSTOMIZED PRINT FUNCTION
 ***************************************************************************************/
extern int _print(msg_src src, msg_type type, const char *fmt, ...);

#if defined (_WIN32) || defined (_WIN64)
extern void enable_console_colorization(); /* enable console colorization for win */
#endif

#endif