
#import <Foundation/Foundation.h>
#import "Capturer.h"
#import "Template.h"
#import "CallbackData.h"
#import "RawImage.h"
#import "swift_callback.h"


/**
	@defgroup SwiftAPI
	@{
*/

/** \~English
	\brief
		Database element.
		If you have several face templates for one person,
		you should create one element for each template
		with the same person_id but different element_id.

	\~Russian
	\brief
		Элемент базы.
		Если имеется несколько шаблонов для одного человека,
		нужно создать по одному элементу для каждого шаблона
		с одинаковыми person_id, но разными element_id.
*/
@interface DatabaseElement : NSObject
{
	void *base_element;
	u_int64_t element_id;
	u_int64_t person_id;
	Template *face_template;
	float distance_treshold;
}
-(nonnull instancetype) init: (void* _Nullable) element;
-(nonnull instancetype) init: (u_int64_t) elem_id : (u_int64_t) pers_id : (Template *_Nullable) face_temp : (float) distance;
-(void) dealloc;

@property (readonly, nonnull)void *base_element;

/** \~English
	\brief
		Unique id of the element.
	\~Russian
	\brief
		Уникальный идентификатор элемента.
*/
@property u_int64_t element_id;

/** \~English
	\brief
		Unique id of the person.
	\~Russian
	\brief
		Уникальный идентификатор человека.
*/
@property u_int64_t person_id;

/** \~English
	\brief
		Distance threshold for a MatchFound event.

	Setting a different recognition threshold for different persons may be useful in some cases.
	For example, if there is a particular criminal in the blacklist, who is more dangerous
	than the other criminals, and you want to increase the recognition probability for this very person,
	despite the higher probability of a false acceptance error.

	\~Russian
	\brief
		Порог распознавания.

	Установка разных порогов распознавания для разных людей может быть полезной в некоторых случаях.
	Например, в том случае, если определенный преступник из черного списка опаснее остальных,
	и вы хотите увеличить вероятность его распознавания,
	несмотря на увеличение вероятности ложного распознавания.
*/
@property float distance_treshold;

/** \~English
	\brief
		Face template.
	\~Russian
	\brief
		Шаблон лица.
*/
@property Template * _Nullable face_template;

@end


/** \~English
	\brief
		VideoWorker is an interface object for tracking, processing and matching faces on multiple video streams.
		We recommend you to use VideoWorker instead of Capturer for face tracking on video streams. When VideoWorker is created with
		<i>matching_thread=0</i> and <i>processing_thread=0</i>, then the standard Capturer license is used.
	\~Russian
	\brief
		VideoWorker - интерфейсный объект для трекинга, обработки
		и распознавания лиц на нескольких видеопотоках. Рекомендуется использовать VideoWorker вместо
		Capturer для детекции лиц на видеопотоках. Если при создании VideoWorker указаны параметры
		<i>matching_thread=0</i> и <i>processing_thread=0</i>, то потребляется обычная лицензия Capturer.
*/
@interface VideoWorker : NSObject
{
    void *video_worker;
    CallbackHandler *handler;
    
}
-(nonnull instancetype) init: (void* _Nonnull) worker;
-(void) dealloc;

/**
	\~English
	\brief
		Add a handler for a Tracking event.
		Thread-safe.

	\param[in]  callback
		Callback function.

	\param[in]  userdata
		Any pointer.
		It will be passed to the callback as a userdata argument.

	\return
		Integer id for this callback.
		Use it for passing to VideoWorker::removeTrackingCallback to unsubscribe.

	\~Russian
	\brief
		Добавить обработчик события трекинга (Tracking).
		Потокобезопасный.

	\param[in]  callback
		Функция коллбэка.

	\param[in]  userdata
		Любой указатель.
		При вызове коллбэка он будет передан через аргумент userdata.

	\return
		Целочисленный идентификатор коллбэка.
		Используйте его для передачи в VideoWorker::removeTrackingCallback, чтобы отписаться.
*/
-(int) addTrackingCallbackU: (const void* _Nonnull)callback : (void * _Nonnull const)userdata;

/**
	\~English
	\brief
		Add a handler for a MatchFound event.
		Thread-safe.

	\param[in]  callback
		Callback function.

	\param[in]  userdata
		Any pointer.
		It will be passed to the callback as a userdata argument.

	\return
		Integer id for this callback.
		Use it for passing to VideoWorker::removeMatchFoundCallback to unsubscribe.

	\~Russian
	\brief
		Добавить обработчик события распознавания (MatchFound).
		Потокобезопасный.

	\param[in]  callback
		Функция коллбэка.

	\param[in]  userdata
		Любой указатель.
		При вызове коллбэка он будет передан через аргумент userdata.

	\return
		Целочисленный идентификатор коллбэка.
		Используйте его для передачи в VideoWorker::removeMatchFoundCallback, чтобы отписаться.
*/
-(int) addMatchFoundCallbackU: (const void* _Nonnull)callback : (void * _Nonnull const)userdata;


/**
	\~English
	\brief
		Add an event handler.
		Thread-safe.

	\param[in]  handler
		A pointer to a custom class inherited from CallbackHandler.

	\~Russian
	\brief
		Добавить обработчик события.
		Потокобезопасный.

	\param[in]  handler
		Указатель на пользовательский класс унаследованного от CallbackHandler.
*/
-(void) addHandlerCallback: (CallbackHandler * _Nonnull) handler;

/**
	\~English
	\brief
		Add a new video frame for a specific video stream.
		Tracking and recognition results will be returned asynchronously
			via Tracking, MatchFound and TrackingLost callbacks.
		Thread-safe.

	\param[in]  frame
		Video frame.
		Only colored images are allowed
		(i.e. IRawImage::FORMAT_RGB, IRawImage::FORMAT_BGR, IRawImage::FORMAT_YUV_NV21 and IRawImage::FORMAT_YUV_NV12).

	\param[in]  stream_id
		Integer id of the video stream
		(0 <= stream_id < streams_count).

	\param[in] timestamp_microsec
		Timestamp of the frame in microseconds

	\return
		Integer id for this frame, unique for this video stream.
		This id will be used to identify this frame in the callbacks.

	\~Russian
	\brief
		Подать новый кадр определенного видеопотока.
		Результаты трекинга и распознавания будут возвращаться асинхронно
		в коллбэках Tracking, MatchFound и TrackingLost.
		Потокобезопасный.

	\param[in]  frame
		Изображение кадра.
		Допустимы только цветные изображения
		(т.е. IRawImage::FORMAT_RGB, IRawImage::FORMAT_BGR, IRawImage::FORMAT_YUV_NV21 и IRawImage::FORMAT_YUV_NV12).

	\param[in]  stream_id
		Целочисленный идентификатор видеопотока
		(0 <= stream_id < streams_count).

	\param[in] timestamp_microsec
		Временная метка кадра в микросекундах

	\return
		Целочисленный идентификатор кадра, уникальный для этого видеопотока,
		который будет использоваться в коллбэках для обозначения этого кадра.
*/
-(int) addVideoFrame: (RawImage * _Nonnull) image : (int) stream_id;

/**
	\~English
	\brief
		Set / replace the database (can be called at any time).
		Available only if matching_threads_count > 0.
		Thread-safe.

	\param[in]  elements
		Vector of database elements.

	\~Russian
	\brief
		Задать / заменить базу (можно вызывать в любое время).
		Доступно только при ненулевом количестве потоков сравнения (matching_threads_count).
		Потокобезопасный.

	\param[in]  elements
		Вектор элементов базы.
*/
-(void) setDatabase: (NSArray<DatabaseElement*>* _Nonnull) elements;

/**
	\~English
	\brief
		Enable the creation of templates for a given stream.
		After that, the matching is resumed as well.
		Thread-safe.

	\param[in]  stream_id
		Integer id of the video stream
		(0 <= stream_id < streams_count).

	\~Russian
	\brief
		Включить генерацию шаблонов для данного потока.
		Соответственно, сравнения также возобновятся.
		Потокобезопасный.

	\param[in]  stream_id
		Целочисленный идентификатор видеопотока
		(0 <= stream_id < streams_count).
*/
-(void) enableProcessingOnStream: (const int) stream_id;

/**
	\~English
	\brief
		Disable the creation of templates for a given stream.
		After that, the matching stops as well.
		Thread-safe.

	\param[in]  stream_id
		Integer id of the video stream
		(0 <= stream_id < streams_count).

	\~Russian
	\brief
		Отключить генерацию шаблонов для данного потока.
		Соответственно, сравнения также остановятся.
		Потокобезопасный.

	\param[in]  stream_id
		Целочисленный идентификатор видеопотока
		(0 <= stream_id < streams_count).
*/
-(void) disableProcessingOnStream: (const int) stream_id;

/**
	\~English
	\brief
		Reset work state for the stream.
		It waits for the callbacks, which are currently being executed, therefore, do not synchronize
		the resetStream call with the code inside the callbacks, otherwise it can cause a deadlock.
		After resetStream is executed, no callbacks related to the previous frames or tracks will be called.
		<b>It is necessary</b> to release the memory allocated for all tracks with track_id less than the return
		value, since <b>there will be no TrackingLost callback</b> for the tracks removed during this reset.
		Thread-safe.

	\param[in]  stream_id
		Integer id of the video stream
		(0 <= stream_id < streams_count).

	\return
		Integer track_id_threshold, which means that all tracks that were
		removed during resetStream had track_id < track_id_threshold,
		and all new tracks will have track_id >= track_id_threshold.

	\~Russian
	\brief
		Сбросить состояние работы для указанного видеопотока.
		В процессе происходит ожидание выполняющихся в данный момент коллбэков, поэтому
		не синхронизируйте вызов resetStream с кодом внутри коллбэков, иначе возможен deadlock.
		После возврата управления от resetStream не будет вызвано ни одного
		коллбэка, относящегося к предыдущим кадрам или трекам.
		<b>Необходимо</b> освободить память, выделенную для треков, track_id которых меньше возвращенного
		значения, так как для треков, удаленных в процессе этого сброса, <b>TrackingLost коллбэк вызван не будет</b>.
		Потокобезопасный.

	\param[in]  stream_id
		Целочисленный идентификатор видеопотока
		(0 <= stream_id < streams_count).

	\return
		Целое число track_id_threshold, означающее, что все удаленные в
		ходе resetStream треки имели track_id < track_id_threshold,
		а все новые треки будут иметь track_id >= track_id_threshold.

*/
-(void) resetStream: (const int) stream_id;
-(void) checkException;
@property (nonnull) CallbackHandler *handler;

@end

/** @} */