#ifndef ANSONVIF_H
#define ANSONVIF_H
#define ANSONVIF_API __declspec(dllexport)
#include "onvif/onvif.h"
#include <iostream>
#include "ANSLicense.h"
#include "LabVIEWHeader/extcode.h"
#include <vector>
#include <mutex>
#include <cstdint>
namespace ANSCENTER
{
	typedef struct
	{
		std::string deviceIP;
		std::string deviceProfileName;
		std::string deviceProfileURI;
	} OnvifDeviceProfile;
	typedef struct
	{
		ONVIF_DEVICE    onvif_device;
		int				flags;      				// FLAG_MANUAL mean added manual, other auto discovery device
		int				state;      				// 0 -- offline; 1 -- online
		void*			p_user;						// user data
		pthread_t		thread_handler;				// get information thread handler
		BOOL			need_update;				// if update device information
		int				snapshot_len;               // devcie snapshot buffer length
		uint8*			snapshot;					// device snapshot buffer
	} ONVIF_DEVICE_EX;
	typedef struct
	{
		std::string deviceIP;
		int			devicePort;
	} OnvifDevice;	

	void StateDetectThread(void* argv);

	PPSN_CTX*	m_dev_fl = nullptr;				// device free list
	PPSN_CTX*	m_dev_ul = nullptr;				// device used list
	BOOL		m_bStateDetect = FALSE;				// device state detect flag
	pthread_t	m_hStateDetect = 0;					// device state detect threand handler
	
	static std::vector<OnvifDevice>	_deviceList;
	class ANSONVIF_API ANSOnvifClient
	{
	private:
		bool						_licenseValid{ false };
		std::string					_licenseKey;
		std::mutex					_mutex;

	private:
		[[nodiscard]] ONVIF_DEVICE_EX* FindDevice(ONVIF_DEVICE_EX* pdevice);
		[[nodiscard]] ONVIF_DEVICE_EX* FindDeviceByEndpointReference(char* p_EndpointReference);
		[[nodiscard]] ONVIF_DEVICE_EX* AddDevice(ONVIF_DEVICE_EX* pdevice);
		void			 FreeDevice(ONVIF_DEVICE_EX* p_dev);
		void			 GetDevInfo(ONVIF_DEVICE_EX* p_device);
		//void			 StartDetectTask();
		//void			 StopDetectTask();
		void			 ClearDevices();
	protected:
		static			void ProbeCallback(DEVICE_BINFO* p_res, int msgtype, void* p_data);
		void			CheckLicense();
		void			ErrorHandler(ONVIF_DEVICE* p_device);

	public:
		[[nodiscard]] bool Init(const std::string& licenseKey);
		~ANSOnvifClient();
		ANSOnvifClient();
		void ClearDeviceList();
		void Destroy();
		[[nodiscard]] std::vector<OnvifDevice> SearchForDevices(int sleepDuration);
		[[nodiscard]] std::vector<OnvifDeviceProfile> SearchForDeviceProfiles(const std::string& username, const std::string& password);
		[[nodiscard]] std::vector<OnvifDeviceProfile> SearchForDeviceProfiles(const std::vector<std::string>& usernameList, const std::vector<std::string>& passwordList);
		[[nodiscard]] std::vector<OnvifDeviceProfile> SearchForDeviceProfile(const std::string& ip, int port, const std::string& username, const std::string& password);
		[[nodiscard]] std::string DeviceListToJsonString(const std::vector<OnvifDevice>& deviceList);
		[[nodiscard]] std::string DeviceProfileToJsonString(const std::vector<OnvifDeviceProfile>& deviceProfileList);
		void		UpdateDevice(ONVIF_DEVICE_EX* p_device);
	};
}
extern "C" __declspec(dllexport) int CreateANSOnvifHandle(ANSCENTER::ANSOnvifClient * *Handle, const char* licenseKey);
extern "C" __declspec(dllexport) int SearchANSOnvifDevices(ANSCENTER::ANSOnvifClient * *Handle, int sleepDuration, std::vector<std::string> &deviceList);
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles(ANSCENTER::ANSOnvifClient * *Handle, const char* username, const char* password, std::vector<std::string> &profileList);
extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles(ANSCENTER::ANSOnvifClient * *Handle, const char* ip, int port, const char* username, const char* password, std::vector<std::string> &profileList);
extern "C" __declspec(dllexport) int SearchANSOnvifDevices_LV(ANSCENTER::ANSOnvifClient * *Handle, int sleepDuration, LStrHandle deviceList);
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles_LV(ANSCENTER::ANSOnvifClient * *Handle, const char* username, const char* password, LStrHandle profileList);
extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles_LV(ANSCENTER::ANSOnvifClient * *Handle, const char* ip, int port, const char* username, const char* password, LStrHandle profileList);
extern "C" __declspec(dllexport) int ReleaseANSOnvifHandle(ANSCENTER::ANSOnvifClient * *Handle);

// V2 entry points — accept handle by value (uint64_t) to fix LabVIEW buffer-reuse bug
extern "C" __declspec(dllexport) int SearchANSOnvifDevices_LV_V2(uint64_t handleVal, int sleepDuration, LStrHandle deviceList);
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles_LV_V2(uint64_t handleVal, const char* username, const char* password, LStrHandle profileList);
extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles_LV_V2(uint64_t handleVal, const char* ip, int port, const char* username, const char* password, LStrHandle profileList);
#endif