//--------------------------------------------------------------------------------------------------
// Copyright (c) id3 Technologies
// All Rights Reserved.
//--------------------------------------------------------------------------------------------------
// ignore_for_file: unused_import
import 'dart:ffi';
import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'face_sdk_generated_bindings.dart';
import 'face_native.dart';

import '../id3_face.dart';

final _finalizer = NativeFinalizer(faceSDK.addresses.id3FaceMatcher_Dispose.cast());

/// Compares two face templates and searches for a face template in a list.
class FaceMatcher implements Finalizable {
  /// Native handle.
  late Pointer<Pointer<id3FaceMatcher>> _pHandle;
  bool _disposable = true;

  /// Gets the native handle.
  /// return The native handle.
  Pointer<id3FaceMatcher> get handle => _pHandle.value;

  /// Creates a new instance of the FaceMatcher class.
  ///
  /// throws FaceException An error has occurred during Face Library execution.
  FaceMatcher() {
    _pHandle = calloc();
    try {
      var err = faceSDK.id3FaceMatcher_Initialize(_pHandle);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      _finalizer.attach(this, _pHandle.cast(), detach: this);
    } finally {}
  }

  /// Creates a new instance of the FaceMatcher class.
  ///
  /// param handle     Handle to the FaceMatcher.
  /// throws FaceException An error has occurred during Face Library execution.
  FaceMatcher.fromHandle(Pointer<id3FaceMatcher> handle) {
    _pHandle = calloc();
    _pHandle.value = handle;
    _disposable = false;
  }

  /// Releases all resources used by this FaceMatcher.
  void dispose() {
    if (_disposable) {
      faceSDK.id3FaceMatcher_Dispose(_pHandle);
      calloc.free(_pHandle);
      _finalizer.detach(this);
    }
  }


  // Public methods
  /// Compares two template lists and outputs a comparison score.
  ///
  /// param referenceList Reference template list.
  /// param probeList Probe template list.
  /// param poolingMethod Pooling method applied during the match process.
  /// return The comparison score, in the range (0;65535).
  /// throws FaceException An error has occurred during Face Library execution.
  int compareTemplateLists(FaceTemplateList referenceList, FaceTemplateList probeList, PoolingMethod poolingMethod) {
    Pointer<Int> pScore = calloc();
    try {
      var err = faceSDK.id3FaceMatcher_CompareTemplateLists(_pHandle.value, referenceList.handle, probeList.handle, poolingMethod.value, pScore);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vScore = pScore.value;
      return vScore;
    } finally {
      calloc.free(pScore);
    }
  }

  /// Compares two templates and outputs a comparison score.
  ///
  /// param reference Reference template.
  /// param probe Probe template.
  /// return The comparison score, in the range (0;65535).
  /// throws FaceException An error has occurred during Face Library execution.
  int compareTemplates(FaceTemplate reference, FaceTemplate probe) {
    Pointer<Int> pScore = calloc();
    try {
      var err = faceSDK.id3FaceMatcher_CompareTemplates(_pHandle.value, reference.handle, probe.handle, pScore);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vScore = pScore.value;
      return vScore;
    } finally {
      calloc.free(pScore);
    }
  }

  /// Performs a one-to-many search of a biometric probe against a previously initialized dictionary of biometric references and outputs a candidate list.
  ///
  /// param referenceDict Reference template dictionary.
  /// param probe Probe template.
  /// param maxCandidates Maximum number of candidates to output.
  /// param candidateList List of candidates sorted by decreasing match score.
  /// throws FaceException An error has occurred during Face Library execution.
  void searchTemplate(FaceTemplateDict referenceDict, FaceTemplate probe, int maxCandidates, FaceCandidateList candidateList) {
    var err = faceSDK.id3FaceMatcher_SearchTemplate(_pHandle.value, referenceDict.handle, probe.handle, maxCandidates, candidateList.handle);
    if (err != FaceError.success.value) {
      throw FaceException(err);
    }
  }

}

