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

import '../id3_face.dart';

/// Handles the license to use this SDK.
class FaceLicense {

  // Public methods
  /// Activates a license using customer credentials and a product reference and saves the license to a file.
  ///
  /// param hardwareCode The hardware code on which the license file will be attached, to be retrieved using the GetHostHardwareCode function.
  /// param login The id3 account login.
  /// param password The id3 account password.
  /// param productReference The requested product reference.
  /// param commentary Commentary associated to this license activation.
  /// param path Path to the retrieved license file.
  /// throws FaceException An error has occurred during Face Library execution.
  static void activate(String? hardwareCode, String? login, String? password, String? productReference, String? commentary, String? path) {
    Pointer<Char>? pHardwareCode = hardwareCode?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pLogin = login?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pPassword = password?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pProductReference = productReference?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pCommentary = commentary?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pPath = path?.toNativeUtf8().cast<Char>();
    try {
      var err = faceSDK.id3FaceLicense_Activate(pHardwareCode ?? nullptr, pLogin ?? nullptr, pPassword ?? nullptr, pProductReference ?? nullptr, pCommentary ?? nullptr, pPath ?? nullptr);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
    } finally {
      if (pHardwareCode != null) {
        calloc.free(pHardwareCode);
      }
      if (pLogin != null) {
        calloc.free(pLogin);
      }
      if (pPassword != null) {
        calloc.free(pPassword);
      }
      if (pProductReference != null) {
        calloc.free(pProductReference);
      }
      if (pCommentary != null) {
        calloc.free(pCommentary);
      }
      if (pPath != null) {
        calloc.free(pPath);
      }
    }
  }

  /// Activates a license file using an activation key and saves the license to a file.
  ///
  /// param hardwareCode The hardware code on which the license file will be attached, to be retrieved using the GetHostHardwareCode function.
  /// param activationKey The activation key.
  /// param commentary Commentary associated to this license activation, generally the host name.
  /// param path Path to the retrieved license file.
  /// throws FaceException An error has occurred during Face Library execution.
  static void activateActivationKey(String? hardwareCode, String? activationKey, String? commentary, String? path) {
    Pointer<Char>? pHardwareCode = hardwareCode?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pActivationKey = activationKey?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pCommentary = commentary?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pPath = path?.toNativeUtf8().cast<Char>();
    try {
      var err = faceSDK.id3FaceLicense_ActivateActivationKey(pHardwareCode ?? nullptr, pActivationKey ?? nullptr, pCommentary ?? nullptr, pPath ?? nullptr);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
    } finally {
      if (pHardwareCode != null) {
        calloc.free(pHardwareCode);
      }
      if (pActivationKey != null) {
        calloc.free(pActivationKey);
      }
      if (pCommentary != null) {
        calloc.free(pCommentary);
      }
      if (pPath != null) {
        calloc.free(pPath);
      }
    }
  }

  /// Activates a license using an activation key and returns the license in a data buffer.
  ///
  /// param hardwareCode The hardware code on which the license file will be attached, to be retrieved using the GetHostHardwareCode function.
  /// param activationKey The id3 activation key.
  /// param commentary Commentary associated to this license activation.
  /// return The license data buffer.
  /// throws FaceException An error has occurred during Face Library execution.
  static Uint8List activateActivationKeyBuffer(String? hardwareCode, String? activationKey, String? commentary) {
    Pointer<Char>? pHardwareCode = hardwareCode?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pActivationKey = activationKey?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pCommentary = commentary?.toNativeUtf8().cast<Char>();
    Pointer<UnsignedChar> pLicenseFileBuffer = calloc.allocate(2048);
    Pointer<Int> pLicenseFileBufferSize = calloc.allocate(1);
    pLicenseFileBufferSize[0] = 2048;
    try {
      var err = faceSDK.id3FaceLicense_ActivateActivationKeyBuffer(pHardwareCode ?? nullptr, pActivationKey ?? nullptr, pCommentary ?? nullptr, pLicenseFileBuffer, pLicenseFileBufferSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicenseFileBuffer);
        pLicenseFileBuffer = calloc.allocate(pLicenseFileBufferSize.value);
        err = faceSDK.id3FaceLicense_ActivateActivationKeyBuffer(pHardwareCode ?? nullptr, pActivationKey ?? nullptr, pCommentary ?? nullptr, pLicenseFileBuffer, pLicenseFileBufferSize);
      }
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vLicenseFileBuffer = Uint8List.fromList(pLicenseFileBuffer.cast<Uint8>().asTypedList(pLicenseFileBufferSize.value));
      return vLicenseFileBuffer;
    } finally {
      if (pHardwareCode != null) {
        calloc.free(pHardwareCode);
      }
      if (pActivationKey != null) {
        calloc.free(pActivationKey);
      }
      if (pCommentary != null) {
        calloc.free(pCommentary);
      }
      calloc.free(pLicenseFileBuffer);
      calloc.free(pLicenseFileBufferSize);
    }
  }

  /// Retrieves a license file buffer using customer credentials and a product reference and returns the license in a data buffer.
  ///
  /// param hardwareCode The hardware code on which the license file will be attached, to be retrieved using the GetHostHardwareCode function.
  /// param login The customer login.
  /// param password The customer password.
  /// param productReference The requested product reference.
  /// param commentary Commentary associated to this license activation, generally the host name.
  /// return The license data.
  /// throws FaceException An error has occurred during Face Library execution.
  static Uint8List activateBuffer(String? hardwareCode, String? login, String? password, String? productReference, String? commentary) {
    Pointer<Char>? pHardwareCode = hardwareCode?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pLogin = login?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pPassword = password?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pProductReference = productReference?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pCommentary = commentary?.toNativeUtf8().cast<Char>();
    Pointer<UnsignedChar> pLicenseFileBuffer = calloc.allocate(2048);
    Pointer<Int> pLicenseFileBufferSize = calloc.allocate(1);
    pLicenseFileBufferSize[0] = 2048;
    try {
      var err = faceSDK.id3FaceLicense_ActivateBuffer(pHardwareCode ?? nullptr, pLogin ?? nullptr, pPassword ?? nullptr, pProductReference ?? nullptr, pCommentary ?? nullptr, pLicenseFileBuffer, pLicenseFileBufferSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicenseFileBuffer);
        pLicenseFileBuffer = calloc.allocate(pLicenseFileBufferSize.value);
        err = faceSDK.id3FaceLicense_ActivateBuffer(pHardwareCode ?? nullptr, pLogin ?? nullptr, pPassword ?? nullptr, pProductReference ?? nullptr, pCommentary ?? nullptr, pLicenseFileBuffer, pLicenseFileBufferSize);
      }
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vLicenseFileBuffer = Uint8List.fromList(pLicenseFileBuffer.cast<Uint8>().asTypedList(pLicenseFileBufferSize.value));
      return vLicenseFileBuffer;
    } finally {
      if (pHardwareCode != null) {
        calloc.free(pHardwareCode);
      }
      if (pLogin != null) {
        calloc.free(pLogin);
      }
      if (pPassword != null) {
        calloc.free(pPassword);
      }
      if (pProductReference != null) {
        calloc.free(pProductReference);
      }
      if (pCommentary != null) {
        calloc.free(pCommentary);
      }
      calloc.free(pLicenseFileBuffer);
      calloc.free(pLicenseFileBufferSize);
    }
  }

  /// Activates a license using a serial key and saves the license to a file.
  ///
  /// param hardwareCode The hardware code on which the license file will be attached, to be retrieved using the GetHostHardwareCode function.
  /// param serialKey The serial key to activate.
  /// param commentary Commentary associated to this license activation, generally the host name.
  /// param path Path to the license file.
  /// throws FaceException An error has occurred during Face Library execution.
  static void activateSerialKey(String? hardwareCode, String? serialKey, String? commentary, String? path) {
    Pointer<Char>? pHardwareCode = hardwareCode?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pSerialKey = serialKey?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pCommentary = commentary?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pPath = path?.toNativeUtf8().cast<Char>();
    try {
      var err = faceSDK.id3FaceLicense_ActivateSerialKey(pHardwareCode ?? nullptr, pSerialKey ?? nullptr, pCommentary ?? nullptr, pPath ?? nullptr);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
    } finally {
      if (pHardwareCode != null) {
        calloc.free(pHardwareCode);
      }
      if (pSerialKey != null) {
        calloc.free(pSerialKey);
      }
      if (pCommentary != null) {
        calloc.free(pCommentary);
      }
      if (pPath != null) {
        calloc.free(pPath);
      }
    }
  }

  /// Activates a license using a serial key and returns the license in a data buffer.
  ///
  /// param hardwareCode The hardware code on which the license file will be attached, to be retrieved using the GetHostHardwareCode function.
  /// param serialKey The id3 serial key.
  /// param commentary Commentary associated to this license activation.
  /// return The license data buffer.
  /// throws FaceException An error has occurred during Face Library execution.
  static Uint8List activateSerialKeyBuffer(String? hardwareCode, String? serialKey, String? commentary) {
    Pointer<Char>? pHardwareCode = hardwareCode?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pSerialKey = serialKey?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pCommentary = commentary?.toNativeUtf8().cast<Char>();
    Pointer<UnsignedChar> pLicenseFileBuffer = calloc.allocate(2048);
    Pointer<Int> pLicenseFileBufferSize = calloc.allocate(1);
    pLicenseFileBufferSize[0] = 2048;
    try {
      var err = faceSDK.id3FaceLicense_ActivateSerialKeyBuffer(pHardwareCode ?? nullptr, pSerialKey ?? nullptr, pCommentary ?? nullptr, pLicenseFileBuffer, pLicenseFileBufferSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicenseFileBuffer);
        pLicenseFileBuffer = calloc.allocate(pLicenseFileBufferSize.value);
        err = faceSDK.id3FaceLicense_ActivateSerialKeyBuffer(pHardwareCode ?? nullptr, pSerialKey ?? nullptr, pCommentary ?? nullptr, pLicenseFileBuffer, pLicenseFileBufferSize);
      }
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vLicenseFileBuffer = Uint8List.fromList(pLicenseFileBuffer.cast<Uint8>().asTypedList(pLicenseFileBufferSize.value));
      return vLicenseFileBuffer;
    } finally {
      if (pHardwareCode != null) {
        calloc.free(pHardwareCode);
      }
      if (pSerialKey != null) {
        calloc.free(pSerialKey);
      }
      if (pCommentary != null) {
        calloc.free(pCommentary);
      }
      calloc.free(pLicenseFileBuffer);
      calloc.free(pLicenseFileBufferSize);
    }
  }

  /// Checks a license from a file.
  /// This function does two things:
  /// - First it loads the license from a file using the given path
  /// - Then it checks the validity of the license regarding the host it is called on (Windows, Linux, Android ...)
  /// Important: Calling this function is required to get access to the license member getters.
  /// Note: The optional parameter is required on Android and must be the JNIEnv* pointer casted as a void*. It can be set as NULL for other devices.
  ///
  /// param licensePath Absolute or relative path to the license file.
  /// throws FaceException An error has occurred during Face Library execution.
  static void checkLicense(String? licensePath) {
    Pointer<Char>? pLicensePath = licensePath?.toNativeUtf8().cast<Char>();
    Pointer<Void> pOptionalParameter = nullptr;
		if (Platform.isAndroid) {
			pOptionalParameter = getJniEnvPtr();
		}
    try {
      var err = faceSDK.id3FaceLicense_CheckLicense(pLicensePath ?? nullptr, pOptionalParameter);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
    } finally {
      if (pLicensePath != null) {
        calloc.free(pLicensePath);
      }
    }
  }

  /// Checks a license from a buffer.
  /// This function does two things:
  /// - First it loads the license from a buffer
  /// - Then it checks the validity of the license regarding the host it is called on (Windows, Linux, Android ...)
  /// Important: Calling one of the license checking function is required to get access to all the license member getters.
  /// Note: The optional parameter is required on Android and must be the JNIEnv* pointer casted as a void*. It can be set as NULL for other devices.
  ///
  /// param licenseData A buffer containing the license file data.
  /// throws FaceException An error has occurred during Face Library execution.
  static void checkLicenseBuffer(Uint8List? licenseData) {
    Pointer<UnsignedChar>? pLicenseData;
    if (licenseData != null) {
    	pLicenseData = calloc.allocate<UnsignedChar>(licenseData.length);
    	pLicenseData.cast<Uint8>().asTypedList(licenseData.length).setAll(0, licenseData);
    }
    Pointer<Void> pOptionalParameter = nullptr;
		if (Platform.isAndroid) {
			pOptionalParameter = getJniEnvPtr();
		}
    try {
      var err = faceSDK.id3FaceLicense_CheckLicenseBuffer(pLicenseData ?? nullptr, licenseData?.length ?? 0, pOptionalParameter);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
    } finally {
      if (pLicenseData != null) {
        calloc.free(pLicenseData);
      }
    }
  }

  /// Checks the license using a buffer containing the license data and a card-based verification process.
  /// It outputs a challenge response for further verification.
  ///
  /// param licenseData A buffer containing the license file data.
  /// return An array to hold the challenge response generated by the host.
  /// throws FaceException An error has occurred during Face Library execution.
  static Uint8List checkLicenseBufferWithCard(Uint8List? licenseData) {
    Pointer<UnsignedChar>? pLicenseData;
    if (licenseData != null) {
    	pLicenseData = calloc.allocate<UnsignedChar>(licenseData.length);
    	pLicenseData.cast<Uint8>().asTypedList(licenseData.length).setAll(0, licenseData);
    }
    Pointer<UnsignedChar> pChallengeR1 = calloc.allocate(16);
    Pointer<Int> pChallengeR1Size = calloc.allocate(1);
    pChallengeR1Size[0] = 16;
    try {
      var err = faceSDK.id3FaceLicense_CheckLicenseBufferWithCard(pLicenseData ?? nullptr, licenseData?.length ?? 0, pChallengeR1, pChallengeR1Size);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pChallengeR1);
        pChallengeR1 = calloc.allocate(pChallengeR1Size.value);
        err = faceSDK.id3FaceLicense_CheckLicenseBufferWithCard(pLicenseData ?? nullptr, licenseData?.length ?? 0, pChallengeR1, pChallengeR1Size);
      }
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vChallengeR1 = Uint8List.fromList(pChallengeR1.cast<Uint8>().asTypedList(pChallengeR1Size.value));
      return vChallengeR1;
    } finally {
      if (pLicenseData != null) {
        calloc.free(pLicenseData);
      }
      calloc.free(pChallengeR1);
      calloc.free(pChallengeR1Size);
    }
  }

  /// Checks the license by using a card-based verification process.
  /// It takes the path to the license file and outputs a challenge response for further verification.
  ///
  /// param licensePath The file path to the license that needs to be checked.
  /// return An array to hold the challenge response generated by the host.
  /// throws FaceException An error has occurred during Face Library execution.
  static Uint8List checkLicenseWithCard(String? licensePath) {
    Pointer<Char>? pLicensePath = licensePath?.toNativeUtf8().cast<Char>();
    Pointer<UnsignedChar> pChallengeR1 = calloc.allocate(16);
    Pointer<Int> pChallengeR1Size = calloc.allocate(1);
    pChallengeR1Size[0] = 16;
    try {
      var err = faceSDK.id3FaceLicense_CheckLicenseWithCard(pLicensePath ?? nullptr, pChallengeR1, pChallengeR1Size);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pChallengeR1);
        pChallengeR1 = calloc.allocate(pChallengeR1Size.value);
        err = faceSDK.id3FaceLicense_CheckLicenseWithCard(pLicensePath ?? nullptr, pChallengeR1, pChallengeR1Size);
      }
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vChallengeR1 = Uint8List.fromList(pChallengeR1.cast<Uint8>().asTypedList(pChallengeR1Size.value));
      return vChallengeR1;
    } finally {
      if (pLicensePath != null) {
        calloc.free(pLicensePath);
      }
      calloc.free(pChallengeR1);
      calloc.free(pChallengeR1Size);
    }
  }

  /// Checks if a module is present in the previously loaded license.
  ///
  /// param moduleName The module name.
  /// throws FaceException An error has occurred during Face Library execution.
  static void checkModule(String? moduleName) {
    Pointer<Char>? pModuleName = moduleName?.toNativeUtf8().cast<Char>();
    try {
      var err = faceSDK.id3FaceLicense_CheckModule(pModuleName ?? nullptr);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
    } finally {
      if (pModuleName != null) {
        calloc.free(pModuleName);
      }
    }
  }

  /// Finalizes the license check process using the provided cryptogram.
  /// It ensures the integrity and authenticity of the license verification.
  ///
  /// param cryptogram A 32-byte array containing the cryptogram used for final verification.
  /// throws FaceException An error has occurred during Face Library execution.
  static void finalizeCheckLicenseWithCard(Uint8List? cryptogram) {
    Pointer<UnsignedChar>? pCryptogram;
    if (cryptogram != null) {
    	pCryptogram = calloc.allocate<UnsignedChar>(cryptogram.length);
    	pCryptogram.cast<Uint8>().asTypedList(cryptogram.length).setAll(0, cryptogram);
    }
    try {
      var err = faceSDK.id3FaceLicense_FinalizeCheckLicenseWithCard(pCryptogram ?? nullptr, cryptogram?.length ?? 0);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
    } finally {
      if (pCryptogram != null) {
        calloc.free(pCryptogram);
      }
    }
  }

  /// Retrieves the license expiry date.
  ///
  /// return The license expiry date.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getExpiryDate() {
    Pointer<Char> pExpiryDate = calloc.allocate(256);
    Pointer<Int> pExpiryDateSize = calloc.allocate(1);
    pExpiryDateSize[0] = 256;
    try {
      var err = faceSDK.id3FaceLicense_GetExpiryDate(pExpiryDate, pExpiryDateSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pExpiryDate);
        pExpiryDate = calloc.allocate(pExpiryDateSize.value);
        err = faceSDK.id3FaceLicense_GetExpiryDate(pExpiryDate, pExpiryDateSize);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vExpiryDate = utf8.decode(Uint8List.fromList(pExpiryDate.cast<Uint8>().asTypedList(pExpiryDateSize.value)));
      return vExpiryDate;
    } finally {
      calloc.free(pExpiryDate);
      calloc.free(pExpiryDateSize);
    }
  }

  /// Retrieves the hardware code of the external drive you run the library on. This function works on Windows only.
  ///
  /// param hardwareCodeType The requested hardware code type. Must be windowsUsb.
  /// param externalDrivePath On Windows to activate a license on a USB device, it must contain the path to the requested USB drive (e.g 'G:\').
  /// return The device hardware code.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getExternalDriveHardwareCode(LicenseHardwareCodeType hardwareCodeType, String? externalDrivePath) {
    Pointer<Char> pCode = calloc.allocate(256);
    Pointer<Int> pCodeSize = calloc.allocate(1);
    pCodeSize[0] = 256;
    Pointer<Char>? pExternalDrivePath = externalDrivePath?.toNativeUtf8().cast<Char>();
    try {
      var err = faceSDK.id3FaceLicense_GetExternalDriveHardwareCode(hardwareCodeType.value, pCode, pCodeSize, pExternalDrivePath ?? nullptr);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pCode);
        pCode = calloc.allocate(pCodeSize.value);
        err = faceSDK.id3FaceLicense_GetExternalDriveHardwareCode(hardwareCodeType.value, pCode, pCodeSize, pExternalDrivePath ?? nullptr);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vCode = utf8.decode(Uint8List.fromList(pCode.cast<Uint8>().asTypedList(pCodeSize.value)));
      return vCode;
    } finally {
      calloc.free(pCode);
      calloc.free(pCodeSize);
      if (pExternalDrivePath != null) {
        calloc.free(pExternalDrivePath);
      }
    }
  }

  /// Retrieves the hardware code of the device using the requested hardware code type.
  /// This function retrieves the hardware code of the device you run the library on.
  /// The optional parameter is required:
  /// - On Android, it must be the JNIEnv* pointer cast as a void*.
  /// - In other cases, it must be set to NULL.
  ///
  /// param hardwareCodeType The requested hardware code type.
  /// return The device hardware code.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getHostHardwareCode(LicenseHardwareCodeType hardwareCodeType) {
    Pointer<Char> pCode = calloc.allocate(256);
    Pointer<Int> pCodeSize = calloc.allocate(1);
    pCodeSize[0] = 256;
    Pointer<Void> pOptionalParameter = nullptr;
		if (Platform.isAndroid) {
			pOptionalParameter = getJniEnvPtr();
		}
    try {
      var err = faceSDK.id3FaceLicense_GetHostHardwareCode(hardwareCodeType.value, pCode, pCodeSize, pOptionalParameter);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pCode);
        pCode = calloc.allocate(pCodeSize.value);
        err = faceSDK.id3FaceLicense_GetHostHardwareCode(hardwareCodeType.value, pCode, pCodeSize, pOptionalParameter);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vCode = utf8.decode(Uint8List.fromList(pCode.cast<Uint8>().asTypedList(pCodeSize.value)));
      return vCode;
    } finally {
      calloc.free(pCode);
      calloc.free(pCodeSize);
    }
  }

  /// Retrieves the hardware code of the previously loaded license.
  ///
  /// return The license hardware code.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getLicenseFileHardwareCode() {
    Pointer<Char> pLicenseFileHardwareCode = calloc.allocate(256);
    Pointer<Int> pLicenseFileHardwareCodeSize = calloc.allocate(1);
    pLicenseFileHardwareCodeSize[0] = 256;
    try {
      var err = faceSDK.id3FaceLicense_GetLicenseFileHardwareCode(pLicenseFileHardwareCode, pLicenseFileHardwareCodeSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicenseFileHardwareCode);
        pLicenseFileHardwareCode = calloc.allocate(pLicenseFileHardwareCodeSize.value);
        err = faceSDK.id3FaceLicense_GetLicenseFileHardwareCode(pLicenseFileHardwareCode, pLicenseFileHardwareCodeSize);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vLicenseFileHardwareCode = utf8.decode(Uint8List.fromList(pLicenseFileHardwareCode.cast<Uint8>().asTypedList(pLicenseFileHardwareCodeSize.value)));
      return vLicenseFileHardwareCode;
    } finally {
      calloc.free(pLicenseFileHardwareCode);
      calloc.free(pLicenseFileHardwareCodeSize);
    }
  }

  /// Retrieves the serial number of the previously loaded license.
  ///
  /// return The license serial number.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getLicenseFileSerial() {
    Pointer<Char> pLicenseFileSerial = calloc.allocate(256);
    Pointer<Int> pLicenseFileSerialSize = calloc.allocate(1);
    pLicenseFileSerialSize[0] = 256;
    try {
      var err = faceSDK.id3FaceLicense_GetLicenseFileSerial(pLicenseFileSerial, pLicenseFileSerialSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicenseFileSerial);
        pLicenseFileSerial = calloc.allocate(pLicenseFileSerialSize.value);
        err = faceSDK.id3FaceLicense_GetLicenseFileSerial(pLicenseFileSerial, pLicenseFileSerialSize);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vLicenseFileSerial = utf8.decode(Uint8List.fromList(pLicenseFileSerial.cast<Uint8>().asTypedList(pLicenseFileSerialSize.value)));
      return vLicenseFileSerial;
    } finally {
      calloc.free(pLicenseFileSerial);
      calloc.free(pLicenseFileSerialSize);
    }
  }

  /// Retrieves the license name.
  ///
  /// return The license name.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getLicenseName() {
    Pointer<Char> pLicenseName = calloc.allocate(256);
    Pointer<Int> pLicenseNameSize = calloc.allocate(1);
    pLicenseNameSize[0] = 256;
    try {
      var err = faceSDK.id3FaceLicense_GetLicenseName(pLicenseName, pLicenseNameSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicenseName);
        pLicenseName = calloc.allocate(pLicenseNameSize.value);
        err = faceSDK.id3FaceLicense_GetLicenseName(pLicenseName, pLicenseNameSize);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vLicenseName = utf8.decode(Uint8List.fromList(pLicenseName.cast<Uint8>().asTypedList(pLicenseNameSize.value)));
      return vLicenseName;
    } finally {
      calloc.free(pLicenseName);
      calloc.free(pLicenseNameSize);
    }
  }

  /// Retrieves the license owner.
  ///
  /// return The license owner.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getLicenseOwner() {
    Pointer<Char> pLicenseOwner = calloc.allocate(256);
    Pointer<Int> pLicenseOwnerSize = calloc.allocate(1);
    pLicenseOwnerSize[0] = 256;
    try {
      var err = faceSDK.id3FaceLicense_GetLicenseOwner(pLicenseOwner, pLicenseOwnerSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicenseOwner);
        pLicenseOwner = calloc.allocate(pLicenseOwnerSize.value);
        err = faceSDK.id3FaceLicense_GetLicenseOwner(pLicenseOwner, pLicenseOwnerSize);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vLicenseOwner = utf8.decode(Uint8List.fromList(pLicenseOwner.cast<Uint8>().asTypedList(pLicenseOwnerSize.value)));
      return vLicenseOwner;
    } finally {
      calloc.free(pLicenseOwner);
      calloc.free(pLicenseOwnerSize);
    }
  }

  /// Retrieves the license path.
  ///
  /// return The license path.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getLicensePath() {
    Pointer<Char> pLicensePath = calloc.allocate(256);
    Pointer<Int> pLicensePathSize = calloc.allocate(1);
    pLicensePathSize[0] = 256;
    try {
      var err = faceSDK.id3FaceLicense_GetLicensePath(pLicensePath, pLicensePathSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicensePath);
        pLicensePath = calloc.allocate(pLicensePathSize.value);
        err = faceSDK.id3FaceLicense_GetLicensePath(pLicensePath, pLicensePathSize);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vLicensePath = utf8.decode(Uint8List.fromList(pLicensePath.cast<Uint8>().asTypedList(pLicensePathSize.value)));
      return vLicensePath;
    } finally {
      calloc.free(pLicensePath);
      calloc.free(pLicensePathSize);
    }
  }

  /// Retrieves the license type.
  ///
  /// return The license type.
  /// throws FaceException An error has occurred during Face Library execution.
  static LicenseType getLicenseType() {
    Pointer<Int32> pFaceLicenseType = calloc();
    try {
      var err = faceSDK.id3FaceLicense_GetLicenseType(pFaceLicenseType);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vFaceLicenseType = LicenseTypeX.fromValue(pFaceLicenseType.value);
      return vFaceLicenseType;
    } finally {
      calloc.free(pFaceLicenseType);
    }
  }

  /// Retrieves the number of modules in the license.
  ///
  /// return The number of modules in the license.
  /// throws FaceException An error has occurred during Face Library execution.
  static int getModuleCount() {
    Pointer<Int> pCount = calloc();
    try {
      var err = faceSDK.id3FaceLicense_GetModuleCount(pCount);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vCount = pCount.value;
      return vCount;
    } finally {
      calloc.free(pCount);
    }
  }

  /// Retrieves the name of the specified license module.
  ///
  /// param index Index of the module, starting from 0.
  /// return The license module name.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getModuleName(int index) {
    Pointer<Char> pName = calloc.allocate(256);
    Pointer<Int> pNameSize = calloc.allocate(1);
    pNameSize[0] = 256;
    try {
      var err = faceSDK.id3FaceLicense_GetModuleName(index, pName, pNameSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pName);
        pName = calloc.allocate(pNameSize.value);
        err = faceSDK.id3FaceLicense_GetModuleName(index, pName, pNameSize);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vName = utf8.decode(Uint8List.fromList(pName.cast<Uint8>().asTypedList(pNameSize.value)));
      return vName;
    } finally {
      calloc.free(pName);
      calloc.free(pNameSize);
    }
  }

  /// Retrieves the value associated to the specified license module.
  ///
  /// param name Name of the requested module.
  /// return The value associated to the licence module.
  /// throws FaceException An error has occurred during Face Library execution.
  static int getModuleValue(String? name) {
    Pointer<Char>? pName = name?.toNativeUtf8().cast<Char>();
    Pointer<Int> pValue = calloc();
    try {
      var err = faceSDK.id3FaceLicense_GetModuleValue(pName ?? nullptr, pValue);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vValue = pValue.value;
      return vValue;
    } finally {
      if (pName != null) {
        calloc.free(pName);
      }
      calloc.free(pValue);
    }
  }

  /// Retrieves the license product reference.
  ///
  /// return The product reference.
  /// throws FaceException An error has occurred during Face Library execution.
  static String getProductReference() {
    Pointer<Char> pProductReference = calloc.allocate(256);
    Pointer<Int> pProductReferenceSize = calloc.allocate(1);
    pProductReferenceSize[0] = 256;
    try {
      var err = faceSDK.id3FaceLicense_GetProductReference(pProductReference, pProductReferenceSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pProductReference);
        pProductReference = calloc.allocate(pProductReferenceSize.value);
        err = faceSDK.id3FaceLicense_GetProductReference(pProductReference, pProductReferenceSize);
        if (err != FaceError.success.value) {
          throw FaceException(err);
        }
      }
      final vProductReference = utf8.decode(Uint8List.fromList(pProductReference.cast<Uint8>().asTypedList(pProductReferenceSize.value)));
      return vProductReference;
    } finally {
      calloc.free(pProductReference);
      calloc.free(pProductReferenceSize);
    }
  }

  /// Retrieves the number of remaining days.
  ///
  /// return The number of remaining days.
  /// throws FaceException An error has occurred during Face Library execution.
  static int getRemainingDays() {
    Pointer<Int> pRemainingDays = calloc();
    try {
      var err = faceSDK.id3FaceLicense_GetRemainingDays(pRemainingDays);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vRemainingDays = pRemainingDays.value;
      return vRemainingDays;
    } finally {
      calloc.free(pRemainingDays);
    }
  }

  /// Reactivates a license file using the host hardware code and the product reference.
  ///
  /// param hardwareCode The hardware code on which the license file will be attached, to be retrieved using the GetHostHardwareCode function.
  /// param productReference The product reference.
  /// param path Path to the license file.
  /// throws FaceException An error has occurred during Face Library execution.
  static void reactivate(String? hardwareCode, String? productReference, String? path) {
    Pointer<Char>? pHardwareCode = hardwareCode?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pProductReference = productReference?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pPath = path?.toNativeUtf8().cast<Char>();
    try {
      var err = faceSDK.id3FaceLicense_Reactivate(pHardwareCode ?? nullptr, pProductReference ?? nullptr, pPath ?? nullptr);
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
    } finally {
      if (pHardwareCode != null) {
        calloc.free(pHardwareCode);
      }
      if (pProductReference != null) {
        calloc.free(pProductReference);
      }
      if (pPath != null) {
        calloc.free(pPath);
      }
    }
  }

  /// Reactivates a license in a data buffer using the host hardware code and the product reference.
  ///
  /// param hardwareCode The hardware code on which the license file will be attached, to be retrieved using the GetHostHardwareCode function.
  /// param productReference The product reference.
  /// return The new license data buffer.
  /// throws FaceException An error has occurred during Face Library execution.
  static Uint8List reactivateBuffer(String? hardwareCode, String? productReference) {
    Pointer<Char>? pHardwareCode = hardwareCode?.toNativeUtf8().cast<Char>();
    Pointer<Char>? pProductReference = productReference?.toNativeUtf8().cast<Char>();
    Pointer<UnsignedChar> pLicenseFileBuffer = calloc.allocate(2048);
    Pointer<Int> pLicenseFileBufferSize = calloc.allocate(1);
    pLicenseFileBufferSize[0] = 2048;
    try {
      var err = faceSDK.id3FaceLicense_ReactivateBuffer(pHardwareCode ?? nullptr, pProductReference ?? nullptr, pLicenseFileBuffer, pLicenseFileBufferSize);
      if (err == FaceError.insufficientBuffer.value) {
        calloc.free(pLicenseFileBuffer);
        pLicenseFileBuffer = calloc.allocate(pLicenseFileBufferSize.value);
        err = faceSDK.id3FaceLicense_ReactivateBuffer(pHardwareCode ?? nullptr, pProductReference ?? nullptr, pLicenseFileBuffer, pLicenseFileBufferSize);
      }
      if (err != FaceError.success.value) {
        throw FaceException(err);
      }
      final vLicenseFileBuffer = Uint8List.fromList(pLicenseFileBuffer.cast<Uint8>().asTypedList(pLicenseFileBufferSize.value));
      return vLicenseFileBuffer;
    } finally {
      if (pHardwareCode != null) {
        calloc.free(pHardwareCode);
      }
      if (pProductReference != null) {
        calloc.free(pProductReference);
      }
      calloc.free(pLicenseFileBuffer);
      calloc.free(pLicenseFileBufferSize);
    }
  }

}

