#ifndef VISION_H
#define VISION_H
#ifdef __cplusplus
extern "C"{
#endif

#include "Types.h"

#if defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64)
    #if defined(SDK_LIBRARY)
        #define SDKSHARED_EXPORT __declspec(dllexport)
    #else
        #define SDKSHARED_EXPORT __declspec(dllimport)
    #endif
#else
    #define SDKSHARED_EXPORT
#endif
/*!
  \file Vision.h
  \brief A C-Style header file that contains all APIs
  */
/*!
 \mainpage
 <table>
 <tr><th>Version  <td>V15.4
 </table>
 \section Description
 This document covers the interface of this SDK
 */
typedef void* Stream;
/*!
 \brief Initial the SDK. This API need to be called only once before calling other APIs except GetVersionInfo
 */
SDKSHARED_EXPORT void Init();

/*!
 \brief Search for devices
 \return Number of devices, when < 0, it means a failure
 */
SDKSHARED_EXPORT int32_t SearchforDevice();

/*!
 \brief Get the device ID
 \param iIndex specify which device, its valid range is [0, NumberOfDevice)
 \return Device ID; If 'iIndex' has an invalid value, return NULL
 */
SDKSHARED_EXPORT const char* GetDeviceID(unsigned int iIndex);

/*!
 \brief Get the device information
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param[out] pDeviceInfo The device information
 */
SDKSHARED_EXPORT void GetDeviceInfo(const char* pDeviceID, SDeviceInfo* pDeviceInfo);

/*!
 \brief Get the information of the local NIC(network interface card) communicating with the specified device and only available when SDeviceInfo.eType == NIC
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param[out] pNICInfo Information of the local NIC
 */
SDKSHARED_EXPORT void GetLocalNICInfo(const char* pDeviceID, SNICInfo* pNICInfo);

/*!
 \brief Set a new IP to the specified device and only available when SDeviceInfo.eType == NIC. Call it before calling "OpenDevice", or after calling it, call "OpenDevice" again.
        \n  Note: If necessary, do the following steps to know the related change:
        \n  1:Call "GetDeviceInfo" to know whether the device is reachable
        \n  2:Call "GetLocalNICInfo" to know whether the local NIC is changed
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pNewIP IP to be set
 \param pNewMask Mask to be set
 \param pNewGateway Gateway to be set
 \return Success or Failure
 */
SDKSHARED_EXPORT bool ForceIP(const char* pDeviceID, const char* pNewIP, const char* pNewMask, const char* pNewGateway);

/*!
 \brief Open a device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \return Success or Failure
 */
SDKSHARED_EXPORT bool OpenDevice(const char* pDeviceID);

/*!
 \brief Get the number of attributes of the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \return Number of attributes, and -1 means a failure
 */
SDKSHARED_EXPORT int GetNumberOfAttribute(const char* pDeviceID);

/*!
 \brief Get the attribute name
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param i specify which attribute, its valid range is [0, NumberOfAttribute)
 \return Attribute name, and NULL means a failure
 */
SDKSHARED_EXPORT const char* GetAttributeName(const char* pDeviceID, unsigned int i);

/*!
 \brief Get the type of an attribute
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pAttrType Attribute type
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttributeType(const char* pDeviceID, const char* pAttrName, EAttrType* pAttrType);

/*!
 \brief Get the access mode of an attribute
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pAttrAccessMode Access mode
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttributeAccessMode(const char* pDeviceID, const char* pAttrName, EAttrAccessMode* pAttrAccessMode);

/*!
 \brief Get the number of entries of an enumeration attribute
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \return Number of entries, and -1 means the attribute is not an enumeraion
 */
SDKSHARED_EXPORT int GetNumberOfEntry(const char* pDeviceID, const char* pAttrName);

/*!
 \brief Get the entry ID
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param i specify which entry, its valid range is [0, NumberOfEntry)
 \return Index of the given entry, and -1 means a failure
 */
SDKSHARED_EXPORT int GetEntryID(const char* pDeviceID, const char* pAttrName, unsigned int i);

/*!
 \brief Get the entry name
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param i specify which entry, its valid range is [0, NumberOfEntry)
 \return Attribute name, and NULL means a failure
 */
SDKSHARED_EXPORT const char* GetEntryName(const char* pDeviceID, const char* pAttrName, unsigned int i);

/*!
 \brief Get the entry name by the entry ID
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param iEntryID ID of an entry, should be get by the above API: GetEntryID
 \return Attribute name, and NULL means a failure
 */
SDKSHARED_EXPORT const char* GetEntryNameByID(const char* pDeviceID, const char* pAttrName, unsigned int iEntryID);

/*!
 \brief Send a command to the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pCmdName Name of the specified command
 \return Success or Failure
 */
SDKSHARED_EXPORT bool SendCommand(const char* pDeviceID, const char* pCmdName);

/*!
 \brief Set a value to the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param iAttrValue Value with type int64_t
 \param eLocation Specify where to set, DDR_T or USER_ROM_T
 \return Success or Failure
 */
SDKSHARED_EXPORT bool SetAttrInt(const char* pDeviceID, const char* pAttrName, int64_t iAttrValue, EAttrLocation eLocation);

/*!
 \brief Set a value to the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param fAttrValue Value with type double
 \param eLocation Specify where to set, DDR_T or USER_ROM_T
 \return Success or Failure
 */
SDKSHARED_EXPORT bool SetAttrFloat(const char* pDeviceID, const char* pAttrName, double fAttrValue, EAttrLocation eLocation);

/*!
 \brief Set a value to the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param pAttrValue Value with type const char*
 \param eLocation Specify where to set, DDR_T or USER_ROM_T
 \return Success or Failure
 */
SDKSHARED_EXPORT bool SetAttrString(const char* pDeviceID, const char* pAttrName, const char* pAttrValue, EAttrLocation eLocation);

/*!
 \brief Get the value of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pValue Value with type int64_t
 \param eLocation Specify where to get, DDR_T or USER_ROM_T
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrInt(const char* pDeviceID, const char* pAttrName, int64_t* pValue, EAttrLocation eLocation);

/*!
 \brief Get the value of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pValue Value with type double
 \param eLocation Specify where to get, DDR_T or USER_ROM_T
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrFloat(const char* pDeviceID, const char* pAttrName, double* pValue, EAttrLocation eLocation);

/*!
 \brief Get the value of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pValue Value with type char*
 \param eLocation Specify where to get, DDR_T or USER_ROM_T
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrString(const char* pDeviceID, const char* pAttrName, char* pValue, EAttrLocation eLocation);

/*!
 \brief Get maximum of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pMaximum Attribute maximum with type int64_t
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrMaxInt(const char* pDeviceID, const char* pAttrName, int64_t* pMaximum);

/*!
 \brief Get maximum of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attributee
 \param[out] pMaximum Attribute maximum with type double
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrMaxFloat(const char* pDeviceID, const char* pAttrName, double* pMaximum);

/*!
 \brief Get minimum of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pMinimum Attribute minimum with type int64_t
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrMinInt(const char* pDeviceID, const char* pAttrName, int64_t* pMinimum);

/*!
 \brief Get minimum of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pMinimum Attribute minimum with type double
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrMinFloat(const char* pDeviceID, const char* pAttrName, double* pMinimum);

/*!
 \brief Get increment of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pIncrement Attribute increment with type int64_t
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrIncInt(const char* pDeviceID, const char* pAttrName, int64_t* pIncrement);

/*!
 \brief Get increment of the specified attribute on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \param pAttrName Name of the specified attribute
 \param[out] pIncrement Attribute increment with type double
 \return Success or Failure
 */
SDKSHARED_EXPORT bool GetAttrIncFloat(const char* pDeviceID, const char* pAttrName, double* pIncrement);

/*!
  \brief Set the target for the next CalibrateCapture().
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param fTarget The target, 0: the frame of the next CalibrateCapture() will be calibrated to average value of its pixels;
          \n  (0,1]: the frame of the next CalibrateCapture() will be calibrated to (maximum of the pixel * fTarget)
  \return Success or Failure
  */
SDKSHARED_EXPORT bool CalibrateSetTarget(const char* pDeviceID, float fTarget);

/*!
  \brief Get the target.
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \return The target
  */
SDKSHARED_EXPORT float CalibrateGetTarget(const char* pDeviceID);

/*!
  \brief Capture frames.
         \n  Note:The captured frames can be cleared by 'CalibrateReset' or successful 'CalibrateDark' or 'CalibrateBright'
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param iFrameNum How many frames used, passing 0 to use the default
  \return Success or Failure
  */
SDKSHARED_EXPORT bool CalibrateCapture(const char* pDeviceID, unsigned int iFrameNum);

/*!
  \brief Clear the frames captured by 'CalibrateCapture'
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \return Success or Failure
  */
SDKSHARED_EXPORT bool CalibrateReset(const char* pDeviceID);

/*!
  \brief Do offset calibration
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param iModeIndex Specify a index for this calibration
  \param pWorkDir Specify a directory to store calibration data, passing NULL to use the current working directory
  \return Success or Failure
  */
SDKSHARED_EXPORT bool CalibrateDark(const char* pDeviceID, unsigned int iModeIndex, const char* pWorkDir);

/*!
  \brief Do gain calibration
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param iModeIndex Specify a index for this calibration
  \param pWorkDir Specify a directory to store calibration data, passing NULL to use the current working directory
  \return Success or Failure
  */
SDKSHARED_EXPORT bool CalibrateBright(const char* pDeviceID, unsigned int iModeIndex, const char* pWorkDir);

/*!
  \brief Download calibration data to the specified device
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param iModeIndex Specify a index for this calibration
  \param iCalType Specify offset or gain data, 0:Offset; 1:Gain and offset
  \param bFlashEnable Specify whether to download to flash memory on the specified device
  \param pWorkDir Specify a directory storing calibration data to be downloaded, passing NULL to use the current working directory
  \param bVerify Specify whether to verify the downloaded data
  \return Success or Failure
  */
SDKSHARED_EXPORT bool DownloadCalDataToDevice(const char* pDeviceID, unsigned int iModeIndex, int iCalType, bool bFlashEnable, const char* pWorkDir, bool bVerify);

/*!
  \brief Enable the calibration with the index 'iModeIndex' on the specified device
  \param iModeIndex The index of a calibration
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \return Success or Failure
  */
SDKSHARED_EXPORT bool OpenCalibrate(const char* pDeviceID, unsigned int iModeIndex);

/*!
  \brief Disable the calibration on the specified device
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \return Success or Failure
  */
SDKSHARED_EXPORT bool CloseCalibrate(const char* pDeviceID);

/*!
  \brief Do defect calibration[Obsolete]
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param iStepType Specify step A or step B, 0:Step A; 1:Step B
  \param pWorkDir Specify a directory to store the defect data, passing NULL to use the current working directory
  \return Success or Failure
  */
SDKSHARED_EXPORT bool CalibrateDefect(const char* pDeviceID, int iStepType, const char* pWorkDir);

/*!
  \brief Download defect data to the specified device[Obsolete]
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param bFlashEnable Specify whether to download to flash memory on the specified device
  \param pWorkDir Specify a directory storing defect data to be downloaded, by default using the current working directory
  \param bVerify Specify whether to verify the downloaded data
  \return Success or Failure
  */
SDKSHARED_EXPORT bool DownloadDefectDataToDevice(const char* pDeviceID, bool bFlashEnable, const char* pWorkDir, bool bVerify);

/*!
  \brief Interrupt a ongoning download
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \return Success or Failure
  */
SDKSHARED_EXPORT bool InterruptDownload(const char* pDeviceID);

/*!
  \brief Download firmware to the specified device
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param fFirmwareFile file path of the firmware
  \param pCBFunc Specify a callback function to get the downloading progress
  \param pCBParam A pointer to a parameter passed into the callback function
  \return Success or Failure
  */
SDKSHARED_EXPORT bool DownloadFirmware(const char* pDeviceID, const char* fFirmwareFile, FirmwareDownloadCbFunc pCBFunc, void* pCBParam);

/*!
  \brief Download flash data to the specified device
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param pIndex The data index. If *pIndex == 65535, pIndex will contain the actual index generated by the SDK
  \param pDataBuf Pointer to a user allocated buffer to store the data
  \param iDataSize The size in bytes of the provided pDataBuf
  \return Success or Failure
  */
SDKSHARED_EXPORT bool DownloadFlashExtendData(const char* pDeviceID, uint16_t* pIndex, char* pDataBuf, int iDataSize);

/*!
  \brief Upload flash data from the specified device
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \param iIndex The data index
  \param pDataBuf Pointer to a user allocated buffer to receive the data. If NULL, pDataSize will contain the minimal size of pDataBuf in bytes
  \param pDataSize Return the mimimal size in bytes of pDataBuf when pDataBuf equals NULL; the size in bytes of the provided pDataBuf when pDataBuf unequals NULL
  \return Success or Failure
  */
SDKSHARED_EXPORT bool UploadFlashExtendData(const char* pDeviceID, uint16_t iIndex, char* pDataBuf, int* pDataSize);

/*!
 \brief Create a stream on the specified device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 \return A stream pointer, and NULL means a failure
 */
SDKSHARED_EXPORT Stream CreateStream(const char* pDeviceID);

/*!
 \brief Get the status of the stream
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 \return The status of the stream
 */
SDKSHARED_EXPORT EStreamStatus GetStreamStatus(Stream pStream);

/*!
 \brief Start the stream.
         \n  Note: After calling this API, SDK will keep receiving frames from the specified device and saving them into the internal buffer until "StopStream" is called.
         \n  When GetFrameInShort is not called in time, or pFrameProcCb is time consuming, the internal buffer may become full.
         \n  At this time, if bOverwrite == true, the last frame in the buffer will be overwritten, otherwise SDK will drop incoming frames until the buffer become not full.
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 \param bOverwrite Specify whether to overwrite the last frame
 \param pFrameProcCb Specify a callback function to process each frame in order
 \param pCbParam A pointer to a parameter passed into the callback function
 \return Success or Failure
 */
SDKSHARED_EXPORT bool StartStream(Stream pStream, bool bOverwrite, FrameProcCbFunc pFrameProcCb, void* pCbParam);

/*!
 \brief Set a parameter to a frame processing
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 \param eProcType Frame processing type
 \param iProcParam Parameter to be set
 \return Success or Failure
 */
SDKSHARED_EXPORT bool SetFrameProc(Stream pStream, EFrameProcType eProcType, int iProcParam);

/*!
 \brief Get the parameter of a frame processing
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 \param eProcType Frame processing type
 \return iProcValue Parameter, -1 means failure
 */
SDKSHARED_EXPORT int GetFrameProc(Stream pStream, EFrameProcType eProcType);

/*!
 \brief Get the frame with 16 pixel bits in the format of little edian and processed by operations specified by "SetFrameProc".
        \n Note:This API tries to get the frame from the internal buffer, and when the buffer is empty, this API will block until one new frame reaches or "StopStream" is called.
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 \param[out] pFrameID ID of the frame
 \param[out] pWidth Width of the frame
 \param[out] pHeight Height of the frame
 \param[out] pTimeCount Time count of the frame
 \return Pointer of the frame, and valid until the next GetFrameInShort is called; When NULL, it means that the stream is stopped or that an error occurs
 */
SDKSHARED_EXPORT unsigned short* GetFrameInShort(Stream pStream, uint16_t* pFrameID, int32_t* pWidth, int32_t* pHeight, uint32_t* pTimeCount);

/*!
 \brief Get the frame with the pixel value mapped to byte and processed by operations specified by "SetFrameProc".
        \n Note:This API tries to get the frame from the internal buffer, and when the buffer is empty, this API will block until one new frame reaches or "StopStream" is called.
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 \param[out] pFrameID ID of the frame
 \param[out] pWidth Width of the frame
 \param[out] pHeight Height of the frame
 \param[out] pTimeCount Time count of the frame
 \return Pointer of the frame, and valid until the next GetFrameInShort is called; When NULL, it means that the stream is stopped or that an error occurs
 */
SDKSHARED_EXPORT char* GetMappedFrame(Stream pStream, uint16_t* pFrameID, int32_t* pWidth, int32_t* pHeight, uint32_t* pTimeCount);

/*!
  \brief Soft trigger
         \n Note: Call this API after setting the acquisition mode to a not continuous mode and calling StartStream(*) to trigger the device to send one single frame.
  \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
  \return Success or Failure
  */
SDKSHARED_EXPORT bool SoftTrigger(const char* pDeviceID);

/*!
 \brief Stop the stream
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 */
SDKSHARED_EXPORT void StopStream(Stream pStream);

/*!
 \brief Destroy the stream
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 */
SDKSHARED_EXPORT void DestroyStream(Stream pStream);

/*!
 \brief Close the device
 \param pDeviceID The device ID, should be gotten by the above API: 'GetDeviceID'
 */
SDKSHARED_EXPORT void CloseDevice(const char* pDeviceID);

/*!
 \brief Get the last error
 \return Pointer of the text of the last error
 */
SDKSHARED_EXPORT const char* GetLastErrorText();

/*!
 \brief Get version information
 \return Pointer of the version text
 */
SDKSHARED_EXPORT const char* GetVersionText();

/*!
 \brief Enable or disable logging of API calls. It is disabled by default and should keep disabled except that the vendor demand to enable it.
 \param bEnable Flag to enable or disable
 \return Success or Failure
 */
SDKSHARED_EXPORT bool SetCallLogEnable(bool bEnable);

/*!
 \brief Enable or disable logging of stream. It is disabled by default and should keep disabled except that the vendor demand to enable it.
 \param pStream Pointer to the instance of a stream class, which is returned by "CreateStream"
 \param pLogFile Specify a log file to enable, and NULL means to disable
 \return Success or Failure
 */
SDKSHARED_EXPORT bool SetStreamLogEnable(Stream pStream, const char* pLogFile);

/*!
 \brief Uninitialize the SDK
 */
SDKSHARED_EXPORT void Uninit();

#ifdef __cplusplus
}
#endif
#endif // VISION_H
