#pragma once

#ifndef		NZ_API
#	define	NZ_API __declspec(dllexport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

#pragma region "NZ_SDK"

typedef enum
{
	NZ_MODEL_UNKNOWN = 0,
	NZ_MODEL_RHINO,
	NZ_MODEL_LEOPARD,
}NZ_MODEL;

typedef enum{ NZ_SESSION_TYPE_LIVE, NZ_SESSION_TYPE_PB }NZ_SESSION_TYPE;
NZ_API HANDLE __stdcall NZ_Create	( NZ_SESSION_TYPE session_type );
NZ_API HANDLE __stdcall NZ_CreateEx	( NZ_SESSION_TYPE session_type, NZ_MODEL model );
NZ_API void   __stdcall NZ_Delete	( HANDLE handle );

typedef enum{ NZ_STREAM_TYPE_VIDEO, NZ_STREAM_TYPE_AUDIO, NZ_STREAM_TYPE_EVENT, NZ_STREAM_TYPE_CAMERA_DISCONNECTED, NZ_STREAM_TYPE_SERVER_DISCONNECTED }NZ_STREAM_TYPE;
typedef enum{ NZ_CODEC_H264, NZ_CODEC_MPEG4, NZ_CODEC_JPEG, NZ_CODEC_YUV420P, NZ_CODEC_PCM, NZ_CODEC_G711A, NZ_CODEC_G711U, NZ_CODEC_G726 }NZ_CODEC;
typedef enum{ NZ_EVT_TYPE_RECORD, NZ_EVT_TYPE_ALARM, NZ_EVT_TYPE_MOTION, NZ_EVT_TYPE_VLOSS_H, NZ_EVT_TYPE_VLOSS_L, NZ_EVT_TYPE_TEXTIN, NZ_EVT_TYPE_DISK_TEMP, NZ_EVT_TYPE_SMART, NZ_EVT_TYPE_DISK_BAD }NZ_EVT_TYPE;
typedef enum{ NZ_STATUS_TYPE_CAMERA_CONNECTED, NZ_STATUS_TYPE_CAMERA_VIDEO_LOSS, NZ_STATUS_TYPE_SERVER_CONNECTED, NZ_STATUS_TYPE_SERVER_VIDEO_LOSS }NZ_STATUS_TYPE;

typedef struct
{
	NZ_CODEC						codec;
	DWORD64							stream;
	int								stream_length;
	BOOL							key_frame;
	DWORD							width;
	DWORD							height;
	BOOL							recording_status;
}NZ_STREAM_VIDEO;

typedef struct
{
	NZ_CODEC						codec;
	DWORD64							stream;
	int								stream_length;
	int								bitrate;
	int								sampling_rate;
	int								channels;
	int								bits_per_sample;
}NZ_STREAM_AUDIO;

typedef struct
{
	NZ_EVT_TYPE						type;
	BOOL							triggered;
	int								data_size;
	DWORD64							extra_data;
}NZ_STREAM_EVENT;

typedef struct
{
	NZ_STATUS_TYPE					type;
	BOOL							triggered;
	int								data_size;
	DWORD64							extra_data;
}NZ_STREAM_STATUS;

typedef struct
{
	NZ_STREAM_TYPE					type;
	int								channel;
	int								stream_no;
	SYSTEMTIME						time;
	DWORD							t;
	WORD							ms;
	union
	{
		NZ_STREAM_VIDEO				video;
		NZ_STREAM_AUDIO				audio;
		NZ_STREAM_EVENT				evt;
		NZ_STREAM_STATUS			status;
	}DATA;
}NZ_STREAM;

#define NZ_CMD_BASEA					0x00000000
#define NZ_CMD_BASEW					0x10000000

#define IS_UNICODE_COMMAND(x)			((x & NZ_CMD_BASEW) != 0)

#ifdef _UNICODE
#define NZ_CMD_BASE						NZ_CMD_BASEW
#else
#define NZ_CMD_BASE						NZ_CMD_BASEA
#endif

typedef enum
{
	NZ_CMD_UNKNOWN					= (NZ_CMD_BASE | 0x00000000),
	NZ_CMD_CONNECT					= (NZ_CMD_BASE | 0x00000001),	// arg1: LPCSTR addr, arg2: LPCSTR port (http=80&rtsp=554), arg3: LPCSTR id, arg4: LPCSTR password
	NZ_CMD_DISCONNECT				= (NZ_CMD_BASE | 0x00000002),

	NZ_CMD_OPEN_VIDEO				= (NZ_CMD_BASE | 0x00010001),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: BOOL auto_play, arg4: HWND parent_window
	NZ_CMD_CLOSE_VIDEO				= (NZ_CMD_BASE | 0x00010002),	// arg1: int channel (1~), arg2: int stream_number (1 or 2)
	NZ_CMD_OPEN_AUDIO				= (NZ_CMD_BASE | 0x00010011),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: BOOL auto_play
	NZ_CMD_CLOSE_AUDIO				= (NZ_CMD_BASE | 0x00010012),	// arg1: int channel (1~), arg2: int stream_number (1 or 2)
	NZ_CMD_OPEN_EVENT				= (NZ_CMD_BASE | 0x00010021),	// arg1: LPCSTR channel_list (1,2,4,5,...)
	NZ_CMD_CLOSE_EVENT				= (NZ_CMD_BASE | 0x00010022),	// arg1: 
	// [NotImplemented]
	NZ_CMD_GET_RECORDED_DATA		= (NZ_CMD_BASE | 0x00011001),	// arg1: int channel (1~), arg2: SYSTEMTIME *from, arg3: SYSTEMTIME *to
	NZ_CMD_GET_STREAM				= (NZ_CMD_BASE | 0x00012001),	// arg1: NZ_STREAM *stream ([VMS] arg1 : int nrs_id(1~), arg2 : NZ_SESSION_TYPE session_type, arg3 : NZ_STREAM* stream)
	NZ_CMD_RELEASE_STREAM			= (NZ_CMD_BASE | 0x00012002),	// arg1: NZ_STREAM *stream

	NZ_CMD_PTZ_MOVE_LEFT			= (NZ_CMD_BASE | 0x00020001),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_MOVE_RIGHT			= (NZ_CMD_BASE | 0x00020002),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_MOVE_UP				= (NZ_CMD_BASE | 0x00020003),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_MOVE_DOWN			= (NZ_CMD_BASE | 0x00020004),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_MOVE_LEFTUP			= (NZ_CMD_BASE | 0x00020005),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_MOVE_LEFTDOWN		= (NZ_CMD_BASE | 0x00020006),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_MOVE_RIGHTUP			= (NZ_CMD_BASE | 0x00020007),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_MOVE_RIGHTDOWN		= (NZ_CMD_BASE | 0x00020008),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_ZOOM_TELE			= (NZ_CMD_BASE | 0x00020011),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	NZ_CMD_PTZ_ZOOM_WIDE			= (NZ_CMD_BASE | 0x00020012),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	// [NotImplemented]
	NZ_CMD_PTZ_FOCUSIN				= (NZ_CMD_BASE | 0x00020013),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	// [NotImplemented]
	NZ_CMD_PTZ_FOCUSOUT				= (NZ_CMD_BASE | 0x00020014),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (1~10), arg4: int stop (0 or 1)
	// [NotImplemented]
	NZ_CMD_PTZ_PRESET_GetListCount	= (NZ_CMD_BASE | 0x00020021),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int *list_count
	// [NotImplemented]
	NZ_CMD_PTZ_PRESET_GetListData	= (NZ_CMD_BASE | 0x00020022),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int list_count, arg4: NZ_PRESET_LIST *list
	NZ_CMD_PTZ_PRESET_SET			= (NZ_CMD_BASE | 0x00020023),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int preset_no
	NZ_CMD_PTZ_PRESET_MOVE			= (NZ_CMD_BASE | 0x00020024),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int preset_no
	NZ_CMD_PTZ_TOUR_START			= (NZ_CMD_BASE | 0x00020031),	// arg1: int channel (1~), arg2: int stream_number (1 or 2)
	NZ_CMD_PTZ_TOUR_STOP			= (NZ_CMD_BASE | 0x00020032),	// arg1: int channel (1~), arg2: int stream_number (1 or 2)
	NZ_CMD_PTZ_AUX					= (NZ_CMD_BASE | 0x00020033),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int aux_number (1 or 2), arg4: int on/off (0 or 1)	// Leopard only

	NZ_CMD_START_TALK				= (NZ_CMD_BASE | 0x00030001),	// arg1: int channel (1~), arg2: int stream_number (1 or 2)
	NZ_CMD_STOP_TALK				= (NZ_CMD_BASE | 0x00030002),	// arg1: int channel (1~), arg2: int stream_number (1 or 2)
	NZ_CMD_SEND_WAVE				= (NZ_CMD_BASE | 0x00030003),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: LPCSTR wav_path, arg4: BOOL on/off

	NZ_CMD_VIEW_RESIZE				= (NZ_CMD_BASE | 0x00040001),	// arg1: int channel (1~), arg2: int stream_number (1 or 2)
	//NZ_CMD_VIEW_SET_SPLIT			= (NZ_CMD_BASE | 0x00040002),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: LPCSTR split_name (#Fixed#_1x1, #Fixed#_2x2, #Fixed#_3x3, #Fixed#_4x4)
	NZ_CMD_VIEW_SHOW_SELECTION		= (NZ_CMD_BASE | 0x00040003),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: BOOL show
	NZ_CMD_VIEW_SHOW_ZONE			= (NZ_CMD_BASE | 0x00040004),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: POINT *pt, arg4: LPCSTR "index=1&pt_count=4&image_width=1920&image_height=1080"
	NZ_CMD_VIEW_SHOW_DETECT			= (NZ_CMD_BASE | 0x00040005),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: RECT *rc_detect, arg4: LPCSTR "show=1&image_width=1920&image_height=1080"
	NZ_CMD_VIEW_SHOW_NAME			= (NZ_CMD_BASE | 0x00040006),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: LPCSTR name, arg4: int size (5~100, default:15)
	NZ_CMD_VIEW_ROTATE				= (NZ_CMD_BASE | 0x00040007),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int degree

	NZ_CMD_PB_OPEN_VIDEO			= (NZ_CMD_BASE | 0x00050001),	// arg1: int channel (1~), arg2: Don't Care, arg3: BOOL auto_play, arg4: HWND parent_window
	NZ_CMD_PB_CLOSE_VIDEO			= (NZ_CMD_BASE | 0x00050002),	// arg1: int channel (1~), arg2: Don't Care
	NZ_CMD_PB_PLAY					= (NZ_CMD_BASE | 0x00050003),	// arg1: int channel (1~), arg2: Don't Care, arg3: LPCSTR arg (refresh=0/1&speed=1&method=forward/backward&date=2014-08-01&time=14-20-00)	// speed: (0:1/2, 1~3:All frame, 4~9:I-frame only)
	NZ_CMD_PB_PAUSE					= (NZ_CMD_BASE | 0x00050004),	// arg1: int channel (1~), arg2: Don't Care
	// [NotImplemented]
	NZ_CMD_PB_SPEED					= (NZ_CMD_BASE | 0x00050005),	// arg1: int channel (1~), arg2: int stream_number (1 or 2), arg3: int speed (0 or 1~)

	// Export Commands
	NZ_CMD_EXPORT_VIDEO				= (NZ_CMD_BASE | 0x00060001),	// arg1: LPCTSTR pstrOption, arg2: LPEXPORTMSGHANDLER hander, arg3: LONG_PTR pHandlerParam
	NZ_CMD_CANCEL_EXPORT_VIDEO		= (NZ_CMD_BASE | 0x00060002),
	NZ_CMD_EXPORT_IMAGE				= (NZ_CMD_BASE | 0x00060003),	// arg1: LPCTSTR pstrOption, arg2: LPEXPORTMSGHANDLER hander, arg3: LONG_PTR pHandlerParam

	// VMS Only Commands
	NZ_CMD_GET_DATAS				= (NZ_CMD_BASE | 0x00100001),	// arg1: NZ_VMS_DATA_TYPE, arg2: LPSTR* ppOutBuffer, arg3: int* pnOutSize
	NZ_CMD_GET_DATA					= (NZ_CMD_BASE | 0x00100002),	// arg1: NZ_VMS_DATA_TYPE, arg2: id, arg3: LPSTR* ppOutBuffer, arg4: int* pnOutSize
	NZ_CMD_ADD_DATA					= (NZ_CMD_BASE | 0x00100003),	// arg1: NZ_VMS_DATA_TYPE, arg2: LPCTSTR pData
	NZ_CMD_UPDATE_DATA				= (NZ_CMD_BASE | 0x00100004),	// arg1: NZ_VMS_DATA_TYPE, arg2: LPCTSTR pData
	NZ_CMD_DELETE_DATA				= (NZ_CMD_BASE | 0x00100005),	// arg1: NZ_VMS_DATA_TYPE, arg2: int nID
	NZ_CMD_SEARCH_USER_LOG			= (NZ_CMD_BASE | 0x00100006),	// arg1: LPCTSTR pstrOption, arg2: LPLOGSEARCHHANDLER hander, arg3: LONG_PTR pHandlerParam
	NZ_CMD_IS_EXTENDED_SYSTEM_LOG	= (NZ_CMD_BASE | 0x00100007),
	NZ_CMD_SEARCH_SYSTEM_LOG		= (NZ_CMD_BASE | 0x00100008),	// arg1: LPCTSTR pstrOption, arg2: LPLOGSEARCHHANDLER hander, arg3: LONG_PTR pHandlerParam

	NZ_CMD_GET_DATAS_EX				= (NZ_CMD_BASE | 0x00101001),	// arg1: LPCTSTR pstrName, arg2: LPSTR* ppOutBuffer, arg3: int* pnOutSize
	NZ_CMD_GET_DATA_EX				= (NZ_CMD_BASE | 0x00101002),	// arg1: LPCTSTR pstrName, arg2: id, arg3: LPSTR* ppOutBuffer, arg4: int* pnOutSize
	NZ_CMD_ADD_DATA_EX				= (NZ_CMD_BASE | 0x00101003),	// arg1: LPCTSTR pstrName, arg2: LPCTSTR pData
	NZ_CMD_UPDATE_DATA_EX			= (NZ_CMD_BASE | 0x00101004),	// arg1: LPCTSTR pstrName, arg2: LPCTSTR pData
	NZ_CMD_DELETE_DATA_EX			= (NZ_CMD_BASE | 0x00101005)	// arg1: LPCTSTR pstrName, arg2: int nID

} NZ_CMD;

NZ_API BOOL __stdcall NZ_Command	( HANDLE handle, NZ_CMD cmd, DWORD_PTR arg1, DWORD_PTR arg2, DWORD_PTR arg3, DWORD_PTR arg4 );

#pragma endregion "NZ_SDK"

#pragma region "NZ_VMS_SDK"


// Create Resource
NZ_API HANDLE __stdcall NZ_VMS_Create();

// Delete Resource
NZ_API void   __stdcall NZ_VMS_Delete(HANDLE handle);


// Error Codes
#define NZ_ERROR_OK					0

// ÀÎÀÚ Á¤º¸µîÀÌ À¯È¿ÇÏÁö ¾Ê´Â °æ¿ì
#define NZ_ERROR_INVALID			1
// ¿¬°á ½ÇÆÐÇÑ °æ¿ì / ¼­¹ö¿Í ¿¬°áµÇ¾î ÀÖÁö ¾ÊÀº °æ¿ì
#define NZ_ERROR_NOT_ONLINE			3
// ³»ºÎÀûÀ¸·Î ¿¡·¯°¡ ¹ß»ýÇÑ °æ¿ì
#define NZ_ERROR_INTERNAL			4
// ÀÌ¹Ì µ¿ÀÛÁßÀÎ °æ¿ì
#define NZ_ERROR_ALREADY_RUNNING	5
// ¿©À¯ °ø°£ÀÌ ¾ø´Â °æ¿ì
#define NZ_ERROR_DISK_FULL			6
// ½Ã½ºÅÛ ¿¡·¯ È®ÀÎ (::GetLastError)
#define NZ_ERROR_SYSTEM_ERROR		7
// µ¥ÀÌÅÍ¸¦ Ã£Áö ¸øÇÑ °æ¿ì
#define NZ_ERROR_NOT_FOUND			8

// ÀÎÁõ ½ÇÆÐÇÑ °æ¿ì
#define NZ_ERROR_SERVER_AUTH		500
// ¼­¹ö·ÎºÎÅÍ ¹ÞÀº Á¤º¸°¡ À¯È¿ÇÏÁö ¾Ê´Â °æ¿ì
#define NZ_ERROR_SERVER_INVALID		501

#define NZ_ERROR_EXCEPTION			1000


// Get last error
NZ_API DWORD __stdcall NZ_VMS_GetLastError(HANDLE handle);

NZ_API void __stdcall NZ_VMS_ReleaseData(LPCSTR pBuffer);

typedef enum
{
	NZ_DATA_TYPE_UNKNOWN = 0,
	NZ_DATA_TYPE_CAMERA = 1,
	NZ_DATA_TYPE_NRS = 2,
	NZ_DATA_TYPE_RECORD_SCHEDULE = 3,
	NZ_DATA_TYPE_USER = 4,
	NZ_DATA_TYPE_CLIENT = 5,
	NZ_DATA_TYPE_FACILITY = 6
} NZ_VMS_DATA_TYPE;

typedef enum
{
	NZ_EXPORT_MESSAGE_STARTED = 0,		// param1 : camera id
	NZ_EXPORT_MESSAGE_FINISHED,			// param1 : camera id, param2 : 0 (Success) / 1 (Fail) / 2 (Cancel)
	NZ_EXPORT_MESSAGE_UPDATED			// param1 : progress percent
} NZ_EXPORT_MESSAGE;

typedef void (__stdcall *LPEXPORTMSGHANDLER)(NZ_EXPORT_MESSAGE eMessage, LONG_PTR pParam1, LONG_PTR pParam2, LONG_PTR pUserParam);

typedef enum
{
	NZ_LOG_SEARCH_MESSAGE_DATA = 0,		// param1 : LPCTSTR data, param2 : LPBOOL (IsCancel)
	NZ_LOG_SEARCH_MESSAGE_FINISHED		// param1 : 0 (No more data) / 1 (More Data)
} NZ_LOG_SEARCH_MESSAGE;

typedef void (__stdcall *LPLOGSEARCHHANDLER)(NZ_LOG_SEARCH_MESSAGE eMessage, LONG_PTR pParam1, LONG_PTR pParam2, LONG_PTR pUserParam);

NZ_API BOOL __stdcall NZ_VMS_Command( HANDLE handle, NZ_CMD cmd, DWORD_PTR arg1, DWORD_PTR arg2, DWORD_PTR arg3, DWORD_PTR arg4, DWORD_PTR arg5 );

#pragma endregion "NZ_VMS_SDK"

#ifdef __cplusplus
}
#endif
