/* VectorNav HSI Calibration Library v1.0.0.2
 *
 * Copyright (c) 2018 VectorNav Technologies, LLC
 *
 * This source code is proprietary to and copyrighted by VectorNav Technologies, LLC and is
 * available solely under license from VectorNav. All rights reserved. If you do not have a
 * license to use this source code from VectorNav, any use hereof is strictly prohibited by
 * U.S. law and other applicable law. This source code is restricted for use solely with the
 * products of VectorNav and as otherwise set forth in any agreement with VectorNav. Any
 * disclosure of this source code to the public or to any third party is also prohibited.
 */
#ifndef _VNEVENT_H_
#define _VNEVENT_H_

#include "vnint.h"
#include "vnenum.h"
#include "vnbool.h"
#include "vncompiler.h"

#if VN_WINDOWS_BASED

  /* Disable some warnings for Visual Studio with -Wall. */
  #if defined(_MSC_VER)
    #pragma warning(push)
    #pragma warning(disable:4668)
    #pragma warning(disable:4820)
    #pragma warning(disable:4255)
  #endif

  #include <Windows.h>

  #if defined(_MSC_VER)
    #pragma warning(pop)
  #endif

#elif VN_UNIX_BASED
  #include <pthread.h>
#else
  #error "Unknown System"
#endif

#ifdef __cplusplus
extern "C" {
#endif

/** \brief Structure representing an event. */
struct VnEvent
{
  int test;
  #if VN_WINDOWS_BASED
  HANDLE handle;
  #elif VN_UNIX_BASED
  pthread_mutex_t mutex;
  pthread_cond_t condition;
  bool isTriggered;
  #endif
};

#ifndef __cplusplus
typedef struct VnEvent VnEvent_t;
#endif

/**\brief Initializes a VnEvent structure.
 * \param[in] event The VnEvent structure to initialize.
 * \return Any errors encountered. */
enum VnError
VnEvent_initialize(
    struct VnEvent *event);

/**\breif Deinitializes the resources associated with the event.
 * \param[in] event The event to deinitialize.
 * \return Any errors encountered. */
enum VnError
VnEvent_deinitialize(
    struct VnEvent *event);

/**\brief Causes the calling thread to wait on an event until the event is signalled.
 *
 * If the event is signalled, the value E_SIGNALED will be returned.
 *
 * \param[in] event The associated VnEvent.
 * \return Any errors encountered. */
enum VnError VnEvent_wait(struct VnEvent *event);

/** \brief Causes the calling thread to wait on an event until the event is signalled.
 *
 * If the event is signalled, the value E_SIGNALED will be returned.
 *
 * \param[in] event The associated VnEvent.
 * \param[in] timeoutUs The number of microseconds to wait before the thread stops waiting on the event. If a timeout
 *     does occur, the value E_TIMEOUT will be returned.
 * \return Any errors encountered. */
enum VnError VnEvent_waitUs(struct VnEvent *event, uint32_t timeoutUs);

/** \brief Causes the calling thread to wait on an event until the event is signalled.
 *
 * If the event is signalled, the value E_SIGNALED will be returned.
 *
 * \param[in] event The associated VnEvent.
 * \param[in] timeoutMs The number of milliseconds to wait before the thread stops waiting on the event. If a timeout
 *     does occur, the value E_TIMEOUT will be returned.
 * \return Any errors encountered. */
enum VnError VnEvent_waitMs(struct VnEvent *event, uint32_t timeoutMs);

/** \brief Signals an event.
 *
 * \param[in] event The associated event.
 * \return Any errors encountered. */
enum VnError VnEvent_signal(struct VnEvent *event);

#ifdef __cplusplus
}
#endif

#endif
