#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#include <pthread.h>
#include <dlfcn.h> 
#endif // !_WIN32
#include "IMVApi.h"
#include "IMVDefines.h"

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>

extern "C"{

#define	MONO_CHANNEL_NUM	1
#define	RGB_CHANNEL_NUM		3
#define	BGR_CHANNEL_NUM		3

#define sleep(ms)	usleep(1000 * ms)

typedef const char*	(IMV_CALL * DLL_GetVersion)							();
typedef int			(IMV_CALL * DLL_EnumDevices)						(OUT IMV_DeviceList *pDeviceList, IN unsigned int interfaceType);
typedef int			(IMV_CALL * DLL_EnumDevicesByUnicast)				(OUT IMV_DeviceList *pDeviceList, IN const char* pIpAddress);
typedef int			(IMV_CALL * DLL_CreateHandle)						(OUT IMV_HANDLE* handle, IN IMV_ECreateHandleMode mode, IN void* pIdentifier);
typedef int			(IMV_CALL * DLL_DestroyHandle)						(IN IMV_HANDLE handle);
typedef int			(IMV_CALL * DLL_GetDeviceInfo)						(IN IMV_HANDLE handle, OUT IMV_DeviceInfo *pDevInfo);
typedef int			(IMV_CALL * DLL_Open)								(IN IMV_HANDLE handle);
typedef int			(IMV_CALL * DLL_OpenEx)								(IN IMV_HANDLE handle, IN IMV_ECameraAccessPermission accessPermission);
typedef bool		(IMV_CALL * DLL_IsOpen)								(IN IMV_HANDLE handle);
typedef int			(IMV_CALL * DLL_Close)								(IN IMV_HANDLE handle);
typedef int			(IMV_CALL * DLL_GIGE_ForceIpAddress)				(IN IMV_HANDLE handle, IN const char* pIpAddress, IN const char* pSubnetMask, IN const char* pGateway);
typedef int			(IMV_CALL * DLL_GIGE_GetAccessPermission)			(IN IMV_HANDLE handle, IMV_ECameraAccessPermission* pAccessPermission);
typedef int			(IMV_CALL * DLL_GIGE_SetAnswerTimeout)				(IN IMV_HANDLE handle, IN unsigned int timeout);
typedef int			(IMV_CALL * DLL_DownLoadGenICamXML)					(IN IMV_HANDLE handle, IN const char* pFullFileName);
typedef int			(IMV_CALL * DLL_SaveDeviceCfg)						(IN IMV_HANDLE handle, IN const char* pFullFileName);
typedef int			(IMV_CALL * DLL_LoadDeviceCfg)						(IN IMV_HANDLE handle, IN const char* pFullFileName, OUT IMV_ErrorList* pErrorList);
typedef int			(IMV_CALL * DLL_WriteUserPrivateData)				(IN IMV_HANDLE handle, IN void* pBuffer, IN_OUT unsigned int* pLength);
typedef int			(IMV_CALL * DLL_ReadUserPrivateData)				(IN IMV_HANDLE handle, OUT void* pBuffer, IN_OUT unsigned int* pLength);
typedef int			(IMV_CALL * DLL_WriteUARTData)						(IN IMV_HANDLE handle, IN void* pBuffer, IN_OUT unsigned int* pLength);
typedef int			(IMV_CALL * DLL_ReadUARTData)						(IN IMV_HANDLE handle, OUT void* pBuffer, IN_OUT unsigned int* pLength);
typedef int			(IMV_CALL * DLL_SubscribeConnectArg)				(IN IMV_HANDLE handle, IN IMV_ConnectCallBack proc, IN void* pUser);
typedef int			(IMV_CALL * DLL_SubscribeParamUpdateArg)			(IN IMV_HANDLE handle, IN IMV_ParamUpdateCallBack proc, IN void* pUser);
typedef int			(IMV_CALL * DLL_SubscribeStreamArg)					(IN IMV_HANDLE handle, IN IMV_StreamCallBack proc, IN void* pUser);
typedef int			(IMV_CALL * DLL_SubscribeMsgChannelArg)				(IN IMV_HANDLE handle, IN IMV_MsgChannelCallBack proc, IN void* pUser);
typedef int			(IMV_CALL * DLL_SetBufferCount)						(IN IMV_HANDLE handle, IN unsigned int nSize);
typedef int			(IMV_CALL * DLL_ClearFrameBuffer)					(IN IMV_HANDLE handle);
typedef int			(IMV_CALL * DLL_GIGE_SetInterPacketTimeout)			(IN IMV_HANDLE handle, IN unsigned int nTimeout);
typedef int			(IMV_CALL * DLL_GIGE_SetSingleResendMaxPacketNum)	(IN IMV_HANDLE handle, IN unsigned int maxPacketNum);
typedef int			(IMV_CALL * DLL_GIGE_SetMaxLostPacketNum)			(IN IMV_HANDLE handle, IN unsigned int maxLostPacketNum);
typedef int			(IMV_CALL * DLL_StartGrabbing)						(IN IMV_HANDLE handle);
typedef int			(IMV_CALL * DLL_StartGrabbingEx)					(IN IMV_HANDLE handle, IN uint64_t maxImagesGrabbed, IN IMV_EGrabStrategy strategy);
typedef bool		(IMV_CALL * DLL_IsGrabbing)							(IN IMV_HANDLE handle);
typedef int			(IMV_CALL * DLL_StopGrabbing)						(IN IMV_HANDLE handle);
typedef int			(IMV_CALL * DLL_AttachGrabbing)						(IN IMV_HANDLE handle, IN IMV_FrameCallBack proc, IN void* pUser);
typedef int			(IMV_CALL * DLL_GetFrame)							(IN IMV_HANDLE handle, OUT IMV_Frame* pFrame, IN unsigned int timeoutMS);
typedef int			(IMV_CALL * DLL_ReleaseFrame)						(IN IMV_HANDLE handle, IN IMV_Frame* pFrame);
typedef int			(IMV_CALL * DLL_CloneFrame)							(IN IMV_HANDLE handle, IN IMV_Frame* pFrame, OUT IMV_Frame* pCloneFrame);
typedef int			(IMV_CALL * DLL_GetChunkDataByIndex)				(IN IMV_HANDLE handle, IN IMV_Frame* pFrame, IN unsigned int index, OUT IMV_ChunkDataInfo *pChunkDataInfo);
typedef int			(IMV_CALL * DLL_GetStatisticsInfo)					(IN IMV_HANDLE handle, OUT IMV_StreamStatisticsInfo* pStreamStatsInfo);
typedef int			(IMV_CALL * DLL_ResetStatisticsInfo)				(IN IMV_HANDLE handle);
typedef bool		(IMV_CALL * DLL_FeatureIsAvailable)					(IN IMV_HANDLE handle, IN const char* pFeatureName);
typedef bool		(IMV_CALL * DLL_FeatureIsReadable)					(IN IMV_HANDLE handle, IN const char* pFeatureName);
typedef bool		(IMV_CALL * DLL_FeatureIsWriteable)					(IN IMV_HANDLE handle, IN const char* pFeatureName);
typedef bool		(IMV_CALL * DLL_FeatureIsStreamable)				(IN IMV_HANDLE handle, IN const char* pFeatureName);
typedef bool		(IMV_CALL * DLL_FeatureIsValid)						(IN IMV_HANDLE handle, IN const char* pFeatureName);
typedef int			(IMV_CALL * DLL_GetIntFeatureValue)					(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT int64_t* pIntValue);
typedef int			(IMV_CALL * DLL_GetIntFeatureMin)					(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT int64_t* pIntValue);
typedef int			(IMV_CALL * DLL_GetIntFeatureMax)					(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT int64_t* pIntValue);
typedef int			(IMV_CALL * DLL_GetIntFeatureInc)					(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT int64_t* pIntValue);
typedef int			(IMV_CALL * DLL_SetIntFeatureValue)					(IN IMV_HANDLE handle, IN const char* pFeatureName, IN int64_t intValue);
typedef int			(IMV_CALL * DLL_GetDoubleFeatureValue)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT double* pDoubleValue);
typedef int			(IMV_CALL * DLL_GetDoubleFeatureMin)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT double* pDoubleValue);
typedef int			(IMV_CALL * DLL_GetDoubleFeatureMax)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT double* pDoubleValue);
typedef int			(IMV_CALL * DLL_SetDoubleFeatureValue)				(IN IMV_HANDLE handle, IN const char* pFeatureName, IN double doubleValue);
typedef int			(IMV_CALL * DLL_GetBoolFeatureValue)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT bool* pBoolValue);
typedef int			(IMV_CALL * DLL_SetBoolFeatureValue)				(IN IMV_HANDLE handle, IN const char* pFeatureName, IN bool boolValue);
typedef int			(IMV_CALL * DLL_GetEnumFeatureValue)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT uint64_t* pEnumValue);
typedef int			(IMV_CALL * DLL_SetEnumFeatureValue)				(IN IMV_HANDLE handle, IN const char* pFeatureName, IN uint64_t enumValue);
typedef int			(IMV_CALL * DLL_GetEnumFeatureSymbol)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT IMV_String* pEnumSymbol);
typedef int			(IMV_CALL * DLL_SetEnumFeatureSymbol)				(IN IMV_HANDLE handle, IN const char* pFeatureName, IN const char* pEnumSymbol);
typedef int			(IMV_CALL * DLL_GetEnumFeatureEntryNum)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT unsigned int* pEntryNum);
typedef int			(IMV_CALL * DLL_GetEnumFeatureEntrys)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT IMV_EnumEntryList* pEnumEntryList);
typedef int			(IMV_CALL * DLL_GetStringFeatureValue)				(IN IMV_HANDLE handle, IN const char* pFeatureName, OUT IMV_String* pStringValue);
typedef int			(IMV_CALL * DLL_SetStringFeatureValue)				(IN IMV_HANDLE handle, IN const char* pFeatureName, IN const char* pStringValue);
typedef int			(IMV_CALL * DLL_ExecuteCommandFeature)				(IN IMV_HANDLE handle, IN const char* pFeatureName);
typedef int			(IMV_CALL * DLL_PixelConvert)						(IN IMV_HANDLE handle, IN_OUT IMV_PixelConvertParam* pstPixelConvertParam);
typedef int			(IMV_CALL * DLL_OpenRecord)							(IN IMV_HANDLE handle, IN IMV_RecordParam *pstRecordParam);
typedef int			(IMV_CALL * DLL_InputOneFrame)						(IN IMV_HANDLE handle, IN IMV_RecordFrameInfoParam *pstRecordFrameInfoParam);
typedef int			(IMV_CALL * DLL_CloseRecord)						(IN IMV_HANDLE handle);


int camera_init();
int camera_start(int epx_time = 12 * 10000);
int camera_stop();
int camera_cap(void** data, int& w, int& h, int time_out);

}