//--------------------------------------------------------------------------------------------------
// Copyright (c) id3 Technologies
// All Rights Reserved.
//--------------------------------------------------------------------------------------------------
// ignore_for_file: unused_import
import 'dart:collection';
import 'dart:convert';
import 'dart:ffi';
import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'bioseal_sdk_generated_bindings.dart';
import 'bioseal_native.dart';

import '../id3_bioseal.dart';

final _finalizer = NativeFinalizer(biosealSDK.addresses.id3BiosealField_Dispose.cast());

/// Represents a field or a dictionary of fields.
class Field extends Object with IterableMixin<Field> implements Finalizable {
  /// Native handle.
  late Pointer<Pointer<id3BiosealField>> _pHandle;
  bool _disposable = true;

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

  /// Creates a new instance of the Field class.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Field() {
    _pHandle = calloc();
    try {
      var err = biosealSDK.id3BiosealField_Initialize(_pHandle);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      _finalizer.attach(this, _pHandle.cast(), detach: this);
    } finally {}
  }

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

  /// Releases all resources used by this Field.
  void dispose() {
    if (_disposable) {
      biosealSDK.id3BiosealField_Dispose(_pHandle);
      calloc.free(_pHandle);
      _finalizer.detach(this);
    }
  }

  /// Gets or sets the element at the specified index.
  operator [](String key) => get(key);

  /// Gets the number of elements contained in the list or dictionary.
  int get count => getCount();

  @override
  Iterator<Field> get iterator => FieldIterator(this);

  ///
  /// The field type.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  FieldType get fieldType => getFieldType();

  ///
  /// The field name.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String get name => getName();

  ///
  /// The field value as a 64-bit integer.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get valueAsInteger => getValueAsInteger();

  ///
  /// The field value as a boolean.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool get valueAsBoolean => getValueAsBoolean();

  ///
  /// The field value as a float.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  double get valueAsFloat => getValueAsFloat();

  ///
  /// The field value as a string.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String get valueAsString => getValueAsString();

  ///
  /// The data as a binary array.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Uint8List get valueAsBinary => getValueAsBinary();

  ///
  /// The field value as a date.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  DateTime? get valueAsDate => getValueAsDate();

  ///
  /// The field value as a time.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  DateTime? get valueAsTime => getValueAsTime();

  ///
  /// The field value as a date/time.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  DateTime? get valueAsDateTime => getValueAsDateTime();

  ///
  /// The field value as a timestamp (without timezone computation).
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get valueAsTimestamp => getValueAsTimestamp();

  ///
  /// The field value as an array of 64-bit integers.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  List<int> get valueAsIntegerArray => getValueAsIntegerArray();

  ///
  /// The field value as an array of booleans.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  List<bool> get valueAsBooleanArray => getValueAsBooleanArray();

  ///
  /// The field value as an array of floats.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  List<double> get valueAsFloatArray => getValueAsFloatArray();

  ///
  /// The field value as an array of strings.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  StringArray get valueAsStringArray => getValueAsStringArray();

  ///
  /// The field value as an array of dates.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  DateTimeArray get valueAsDateTimeArray => getValueAsDateTimeArray();

  ///
  /// The field value as an array of timestamp.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  List<int> get valueAsTimestampArray => getValueAsTimestampArray();

  ///
  /// A value indicating whether if the field is null.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool get isNull => getIsNull();

  ///
  /// A value indicating whether the field (or one of its child fields) contains biometric data.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool get containsBiometrics => getContainsBiometrics();

  ///
  /// The field extension type.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  FieldExtensionType get extensionType => getExtensionType();

  ///
  /// The field extension.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Extension? get fieldExtension => getFieldExtension();

  ///
  /// The visibility condition.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  VisibilityCondition get visibilityCondition => getVisibilityCondition();

  ///
  /// Gets a string list containing the keys in the dict.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  StringArray get keys => getKeys();

  // Public methods
  /// Gets an item of the Field object.
  ///
  /// param key Unique key of the Field item to get.
  /// return Field item to get.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Field get(String? key) {
    Pointer<Char>? pKey = key?.toNativeUtf8().cast<Char>();
    Field fieldItem = Field();
    try {
      var err = biosealSDK.id3BiosealField_Get(_pHandle.value, pKey ?? nullptr, fieldItem.handle);
      if (err != BiosealError.success.value) {
        fieldItem.dispose();
        throw BiosealException(err);
      }
      return fieldItem;
    } finally {
      if (pKey != null) {
        calloc.free(pKey);
      }
    }
  }

  /// Gets the number of elements in the Field object.
  ///
  /// return Number of elements in the Field object.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getCount() {
    Pointer<Int> pCount = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetCount(_pHandle.value, pCount);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vCount = pCount.value;
      return vCount;
    } finally {
      calloc.free(pCount);
    }
  }

  /// Determines whether the Fieldobject contains the specified key.
  ///
  /// param key The key to locate in the Field object.
  /// return true if the Field object contains an element with the specified key, otherwise false.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool containsKey(String? key) {
    Pointer<Char>? pKey = key?.toNativeUtf8().cast<Char>();
    Pointer<Bool> pResult = calloc();
    try {
      var err = biosealSDK.id3BiosealField_ContainsKey(_pHandle.value, pKey ?? nullptr, pResult);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vResult = pResult.value;
      return vResult;
    } finally {
      if (pKey != null) {
        calloc.free(pKey);
      }
      calloc.free(pResult);
    }
  }

  /// Gets the the field type.
  ///
  /// return The field type.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  FieldType getFieldType() {
    Pointer<Int32> pFieldType = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetFieldType(_pHandle.value, pFieldType);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vFieldType = FieldTypeX.fromValue(pFieldType.value);
      return vFieldType;
    } finally {
      calloc.free(pFieldType);
    }
  }

  /// Gets the the field name.
  ///
  /// return The field name.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String getName() {
    Pointer<Char> pName = nullptr;
    Pointer<Int> pNameSize = calloc.allocate(1);
    pNameSize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetName(_pHandle.value, pName, pNameSize);
      if (err == BiosealError.insufficientBuffer.value) {
        pName = calloc.allocate(pNameSize.value);
        err = biosealSDK.id3BiosealField_GetName(_pHandle.value, pName, pNameSize);
        if (err != BiosealError.success.value) {
          throw BiosealException(err);
        }
      }
      final vName = utf8.decode(Uint8List.fromList(pName.cast<Uint8>().asTypedList(pNameSize.value)));
      return vName;
    } finally {
      calloc.free(pName);
      calloc.free(pNameSize);
    }
  }

  /// Gets the the field value as a 64-bit integer.
  ///
  /// return The field value as a 64-bit integer.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getValueAsInteger() {
    Pointer<LongLong> pValueAsInteger = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsInteger(_pHandle.value, pValueAsInteger);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsInteger = pValueAsInteger.value;
      return vValueAsInteger;
    } finally {
      calloc.free(pValueAsInteger);
    }
  }

  /// Gets the the field value as a boolean.
  ///
  /// return The field value as a boolean.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool getValueAsBoolean() {
    Pointer<Bool> pValueAsBoolean = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsBoolean(_pHandle.value, pValueAsBoolean);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsBoolean = pValueAsBoolean.value;
      return vValueAsBoolean;
    } finally {
      calloc.free(pValueAsBoolean);
    }
  }

  /// Gets the the field value as a float.
  ///
  /// return The field value as a float.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  double getValueAsFloat() {
    Pointer<Float> pValueAsFloat = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsFloat(_pHandle.value, pValueAsFloat);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsFloat = pValueAsFloat.value;
      return vValueAsFloat;
    } finally {
      calloc.free(pValueAsFloat);
    }
  }

  /// Gets the the field value as a string.
  ///
  /// return The field value as a string.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String getValueAsString() {
    Pointer<Char> pValueAsString = nullptr;
    Pointer<Int> pValueAsStringSize = calloc.allocate(1);
    pValueAsStringSize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsString(_pHandle.value, pValueAsString, pValueAsStringSize);
      if (err == BiosealError.insufficientBuffer.value) {
        pValueAsString = calloc.allocate(pValueAsStringSize.value);
        err = biosealSDK.id3BiosealField_GetValueAsString(_pHandle.value, pValueAsString, pValueAsStringSize);
        if (err != BiosealError.success.value) {
          throw BiosealException(err);
        }
      }
      final vValueAsString = utf8.decode(Uint8List.fromList(pValueAsString.cast<Uint8>().asTypedList(pValueAsStringSize.value)));
      return vValueAsString;
    } finally {
      calloc.free(pValueAsString);
      calloc.free(pValueAsStringSize);
    }
  }

  /// Gets the the data as a binary array.
  ///
  /// return The data as a binary array.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Uint8List getValueAsBinary() {
    Pointer<UnsignedChar> pValueAsBinary = nullptr;
    Pointer<Int> pValueAsBinarySize = calloc();
    pValueAsBinarySize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsBinary(_pHandle.value, pValueAsBinary, pValueAsBinarySize);
      if (err == BiosealError.insufficientBuffer.value) {
        pValueAsBinary = calloc.allocate(pValueAsBinarySize.value);
        err = biosealSDK.id3BiosealField_GetValueAsBinary(_pHandle.value, pValueAsBinary, pValueAsBinarySize);
      }
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsBinary = Uint8List.fromList(pValueAsBinary.cast<Uint8>().asTypedList(pValueAsBinarySize.value));
      return vValueAsBinary;
    } finally {
      calloc.free(pValueAsBinary);
      calloc.free(pValueAsBinarySize);
    }
  }

  /// Gets the the field value as a date.
  ///
  /// return The field value as a date.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  DateTime? getValueAsDate() {
    DateTime valueAsDate = DateTime();
    var err = biosealSDK.id3BiosealField_GetValueAsDate(_pHandle.value, valueAsDate.handle);
    if (err == BiosealError.objectDoesNotExist.value) {
      valueAsDate.dispose();
      return null;
    }
    if (err != BiosealError.success.value) {
      valueAsDate.dispose();
      throw BiosealException(err);
    }
    return valueAsDate;
  }

  /// Gets the the field value as a time.
  ///
  /// return The field value as a time.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  DateTime? getValueAsTime() {
    DateTime valueAsTime = DateTime();
    var err = biosealSDK.id3BiosealField_GetValueAsTime(_pHandle.value, valueAsTime.handle);
    if (err == BiosealError.objectDoesNotExist.value) {
      valueAsTime.dispose();
      return null;
    }
    if (err != BiosealError.success.value) {
      valueAsTime.dispose();
      throw BiosealException(err);
    }
    return valueAsTime;
  }

  /// Gets the the field value as a date/time.
  ///
  /// return The field value as a date/time.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  DateTime? getValueAsDateTime() {
    DateTime valueAsDateTime = DateTime();
    var err = biosealSDK.id3BiosealField_GetValueAsDateTime(_pHandle.value, valueAsDateTime.handle);
    if (err == BiosealError.objectDoesNotExist.value) {
      valueAsDateTime.dispose();
      return null;
    }
    if (err != BiosealError.success.value) {
      valueAsDateTime.dispose();
      throw BiosealException(err);
    }
    return valueAsDateTime;
  }

  /// Gets the the field value as a timestamp (without timezone computation).
  ///
  /// return The field value as a timestamp (without timezone computation).
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getValueAsTimestamp() {
    Pointer<LongLong> pValueAsTimestamp = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsTimestamp(_pHandle.value, pValueAsTimestamp);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsTimestamp = pValueAsTimestamp.value;
      return vValueAsTimestamp;
    } finally {
      calloc.free(pValueAsTimestamp);
    }
  }

  /// Gets the the field value as an array of 64-bit integers.
  ///
  /// return The field value as an array of 64-bit integers.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  List<int> getValueAsIntegerArray() {
    Pointer<LongLong> pValueAsIntegerArray = nullptr;
    Pointer<Int> pValueAsIntegerArraySize = calloc();
    pValueAsIntegerArraySize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsIntegerArray(_pHandle.value, pValueAsIntegerArray, pValueAsIntegerArraySize);
      if (err == BiosealError.insufficientBuffer.value) {
        pValueAsIntegerArray = calloc.allocate(pValueAsIntegerArraySize.value);
        err = biosealSDK.id3BiosealField_GetValueAsIntegerArray(_pHandle.value, pValueAsIntegerArray, pValueAsIntegerArraySize);
      }
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsIntegerArray = Int64List.fromList(pValueAsIntegerArray.cast<Int64>().asTypedList(pValueAsIntegerArraySize.value));
      return vValueAsIntegerArray;
    } finally {
      calloc.free(pValueAsIntegerArray);
      calloc.free(pValueAsIntegerArraySize);
    }
  }

  /// Gets the the field value as an array of booleans.
  ///
  /// return The field value as an array of booleans.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  List<bool> getValueAsBooleanArray() {
    Pointer<Bool> pValueAsBooleanArray = nullptr;
    Pointer<Int> pValueAsBooleanArraySize = calloc();
    pValueAsBooleanArraySize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsBooleanArray(_pHandle.value, pValueAsBooleanArray, pValueAsBooleanArraySize);
      if (err == BiosealError.insufficientBuffer.value) {
        pValueAsBooleanArray = calloc.allocate(pValueAsBooleanArraySize.value);
        err = biosealSDK.id3BiosealField_GetValueAsBooleanArray(_pHandle.value, pValueAsBooleanArray, pValueAsBooleanArraySize);
      }
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsBooleanArray = List<bool>.filled(pValueAsBooleanArraySize.value, false);
      for (int i = 0; i < pValueAsBooleanArraySize.value; i++) {
          vValueAsBooleanArray[i] = pValueAsBooleanArray[i];
      }
      return vValueAsBooleanArray;
    } finally {
      calloc.free(pValueAsBooleanArray);
      calloc.free(pValueAsBooleanArraySize);
    }
  }

  /// Gets the the field value as an array of floats.
  ///
  /// return The field value as an array of floats.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  List<double> getValueAsFloatArray() {
    Pointer<Float> pValueAsFloatArray = nullptr;
    Pointer<Int> pValueAsFloatArraySize = calloc();
    pValueAsFloatArraySize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsFloatArray(_pHandle.value, pValueAsFloatArray, pValueAsFloatArraySize);
      if (err == BiosealError.insufficientBuffer.value) {
        pValueAsFloatArray = calloc.allocate(pValueAsFloatArraySize.value);
        err = biosealSDK.id3BiosealField_GetValueAsFloatArray(_pHandle.value, pValueAsFloatArray, pValueAsFloatArraySize);
      }
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsFloatArray = Float32List.fromList(pValueAsFloatArray.cast<Float>().asTypedList(pValueAsFloatArraySize.value));
      return vValueAsFloatArray;
    } finally {
      calloc.free(pValueAsFloatArray);
      calloc.free(pValueAsFloatArraySize);
    }
  }

  /// Gets the the field value as an array of strings.
  ///
  /// return The field value as an array of strings.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  StringArray getValueAsStringArray() {
    StringArray valueAsStringArray = StringArray();
    var err = biosealSDK.id3BiosealField_GetValueAsStringArray(_pHandle.value, valueAsStringArray.handle);
    if (err != BiosealError.success.value) {
      valueAsStringArray.dispose();
      throw BiosealException(err);
    }
    return valueAsStringArray;
  }

  /// Gets the the field value as an array of dates.
  ///
  /// return The field value as an array of dates.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  DateTimeArray getValueAsDateTimeArray() {
    DateTimeArray valueAsDateTimeArray = DateTimeArray();
    var err = biosealSDK.id3BiosealField_GetValueAsDateTimeArray(_pHandle.value, valueAsDateTimeArray.handle);
    if (err != BiosealError.success.value) {
      valueAsDateTimeArray.dispose();
      throw BiosealException(err);
    }
    return valueAsDateTimeArray;
  }

  /// Gets the the field value as an array of timestamp.
  ///
  /// return The field value as an array of timestamp.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  List<int> getValueAsTimestampArray() {
    Pointer<LongLong> pValueAsTimestampArray = nullptr;
    Pointer<Int> pValueAsTimestampArraySize = calloc();
    pValueAsTimestampArraySize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetValueAsTimestampArray(_pHandle.value, pValueAsTimestampArray, pValueAsTimestampArraySize);
      if (err == BiosealError.insufficientBuffer.value) {
        pValueAsTimestampArray = calloc.allocate(pValueAsTimestampArraySize.value);
        err = biosealSDK.id3BiosealField_GetValueAsTimestampArray(_pHandle.value, pValueAsTimestampArray, pValueAsTimestampArraySize);
      }
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValueAsTimestampArray = Int64List.fromList(pValueAsTimestampArray.cast<Int64>().asTypedList(pValueAsTimestampArraySize.value));
      return vValueAsTimestampArray;
    } finally {
      calloc.free(pValueAsTimestampArray);
      calloc.free(pValueAsTimestampArraySize);
    }
  }

  /// Gets the A value indicating whether if the field is null.
  ///
  /// return A value indicating whether if the field is null.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool getIsNull() {
    Pointer<Bool> pIsNull = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetIsNull(_pHandle.value, pIsNull);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vIsNull = pIsNull.value;
      return vIsNull;
    } finally {
      calloc.free(pIsNull);
    }
  }

  /// Gets the A value indicating whether the field (or one of its child fields) contains biometric data.
  ///
  /// return A value indicating whether the field (or one of its child fields) contains biometric data.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool getContainsBiometrics() {
    Pointer<Bool> pContainsBiometrics = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetContainsBiometrics(_pHandle.value, pContainsBiometrics);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vContainsBiometrics = pContainsBiometrics.value;
      return vContainsBiometrics;
    } finally {
      calloc.free(pContainsBiometrics);
    }
  }

  /// Gets the the field extension type.
  ///
  /// return The field extension type.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  FieldExtensionType getExtensionType() {
    Pointer<Int32> pExtensionType = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetExtensionType(_pHandle.value, pExtensionType);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vExtensionType = FieldExtensionTypeX.fromValue(pExtensionType.value);
      return vExtensionType;
    } finally {
      calloc.free(pExtensionType);
    }
  }

  /// Gets the the field extension.
  ///
  /// return The field extension.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Extension? getFieldExtension() {
    Extension fieldExtension = Extension();
    var err = biosealSDK.id3BiosealField_GetFieldExtension(_pHandle.value, fieldExtension.handle);
    if (err == BiosealError.objectDoesNotExist.value) {
      fieldExtension.dispose();
      return null;
    }
    if (err != BiosealError.success.value) {
      fieldExtension.dispose();
      throw BiosealException(err);
    }
    return fieldExtension;
  }

  /// Gets the the visibility condition.
  ///
  /// return The visibility condition.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  VisibilityCondition getVisibilityCondition() {
    Pointer<Int32> pVisibilityCondition = calloc();
    try {
      var err = biosealSDK.id3BiosealField_GetVisibilityCondition(_pHandle.value, pVisibilityCondition);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vVisibilityCondition = VisibilityConditionX.fromValue(pVisibilityCondition.value);
      return vVisibilityCondition;
    } finally {
      calloc.free(pVisibilityCondition);
    }
  }

  /// Gets the gets a string list containing the keys in the dict.
  ///
  /// return Gets a string list containing the keys in the dict.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  StringArray getKeys() {
    StringArray keys = StringArray();
    var err = biosealSDK.id3BiosealField_GetKeys(_pHandle.value, keys.handle);
    if (err != BiosealError.success.value) {
      keys.dispose();
      throw BiosealException(err);
    }
    return keys;
  }

  /// Gets the object at the specified index.
  ///
  /// param index The index of the object to retrieve.
  /// return The field that contains the object.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Field getObjectAtIndex(int index) {
    Field item = Field();
    var err = biosealSDK.id3BiosealField_GetObjectAtIndex(_pHandle.value, index, item.handle);
    if (err != BiosealError.success.value) {
      item.dispose();
      throw BiosealException(err);
    }
    return item;
  }

  /// Gets the binary data at the specified index.
  ///
  /// param index The index of the binary field to retrieve.
  /// return The binary data.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Uint8List getBinaryAtIndex(int index) {
    Pointer<UnsignedChar> pItem = nullptr;
    Pointer<Int> pItemSize = calloc();
    pItemSize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetBinaryAtIndex(_pHandle.value, index, pItem, pItemSize);
      if (err == BiosealError.insufficientBuffer.value) {
        pItem = calloc.allocate(pItemSize.value);
        err = biosealSDK.id3BiosealField_GetBinaryAtIndex(_pHandle.value, index, pItem, pItemSize);
      }
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vItem = Uint8List.fromList(pItem.cast<Uint8>().asTypedList(pItemSize.value));
      return vItem;
    } finally {
      calloc.free(pItem);
      calloc.free(pItemSize);
    }
  }

  /// Set the time zone offset in seconds.
  ///
  /// param offsetInSeconds The time zone offset in seconds.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  void setTimeZoneOffset(int offsetInSeconds) {
    var err = biosealSDK.id3BiosealField_SetTimeZoneOffset(_pHandle.value, offsetInSeconds);
    if (err != BiosealError.success.value) {
      throw BiosealException(err);
    }
  }

  /// Returns a value indicating whether the field (or one of its child fields) contains an extension of the specified type.
  ///
  /// param extensionType The field extension type.
  /// return A value indicating whether the field (or one of its child fields) contains the specified extension.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool containsExtension(FieldExtensionType extensionType) {
    Pointer<Bool> pResult = calloc();
    try {
      var err = biosealSDK.id3BiosealField_ContainsExtension(_pHandle.value, extensionType.value, pResult);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vResult = pResult.value;
      return vResult;
    } finally {
      calloc.free(pResult);
    }
  }

  /// Returns a value indicating whether the field (or one of its child fields) contains an extension with specified name.
  ///
  /// param extensionName A string that identifies the extension.
  /// return A value indicating whether the field (or one of its child fields) contains the specified extension.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool containsExtensionByName(String? extensionName) {
    Pointer<Char>? pExtensionName = extensionName?.toNativeUtf8().cast<Char>();
    Pointer<Bool> pResult = calloc();
    try {
      var err = biosealSDK.id3BiosealField_ContainsExtensionByName(_pHandle.value, pExtensionName ?? nullptr, pResult);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vResult = pResult.value;
      return vResult;
    } finally {
      if (pExtensionName != null) {
        calloc.free(pExtensionName);
      }
      calloc.free(pResult);
    }
  }

  /// Returns a value indicating whether the field (or one of its child fields) contains biometric data of the specified type and/or format.
  ///
  /// param biometricDataType The biometric data type.
  /// param biometricFormat The biometric data format.
  /// return A value indicating whether the field (or one of its child fields) contains biometric data of the specified type and/or format.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool containsBiometricData(BiometricDataType biometricDataType, String? biometricFormat) {
    Pointer<Char>? pBiometricFormat = biometricFormat?.toNativeUtf8().cast<Char>();
    Pointer<Bool> pResult = calloc();
    try {
      var err = biosealSDK.id3BiosealField_ContainsBiometricData(_pHandle.value, biometricDataType.value, pBiometricFormat ?? nullptr, pResult);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vResult = pResult.value;
      return vResult;
    } finally {
      if (pBiometricFormat != null) {
        calloc.free(pBiometricFormat);
      }
      calloc.free(pResult);
    }
  }

  /// Retrieves the localized label based on the provided language code.
  ///
  /// param language The language code for which the label should be localized (e.g., 'en' for English, 'fr' for French).
  /// return The localized label corresponding to the provided language code.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String getLocalizedLabel(String? language) {
    Pointer<Char>? pLanguage = language?.toNativeUtf8().cast<Char>();
    Pointer<Char> pLabel = nullptr;
    Pointer<Int> pLabelSize = calloc.allocate(1);
    pLabelSize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetLocalizedLabel(_pHandle.value, pLanguage ?? nullptr, pLabel, pLabelSize);
      if (err == BiosealError.insufficientBuffer.value) {
        pLabel = calloc.allocate(pLabelSize.value);
        err = biosealSDK.id3BiosealField_GetLocalizedLabel(_pHandle.value, pLanguage ?? nullptr, pLabel, pLabelSize);
        if (err != BiosealError.success.value) {
          throw BiosealException(err);
        }
      }
      final vLabel = utf8.decode(Uint8List.fromList(pLabel.cast<Uint8>().asTypedList(pLabelSize.value)));
      return vLabel;
    } finally {
      if (pLanguage != null) {
        calloc.free(pLanguage);
      }
      calloc.free(pLabel);
      calloc.free(pLabelSize);
    }
  }

  /// Retrieves the localized value based on the provided language code.
  ///
  /// param language The language code for which the value should be localized (e.g., 'en' for English, 'fr' for French).
  /// return The localized value corresponding to the provided language code.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String getLocalizedValue(String? language) {
    Pointer<Char>? pLanguage = language?.toNativeUtf8().cast<Char>();
    Pointer<Char> pValue = nullptr;
    Pointer<Int> pValueSize = calloc.allocate(1);
    pValueSize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealField_GetLocalizedValue(_pHandle.value, pLanguage ?? nullptr, pValue, pValueSize);
      if (err == BiosealError.insufficientBuffer.value) {
        pValue = calloc.allocate(pValueSize.value);
        err = biosealSDK.id3BiosealField_GetLocalizedValue(_pHandle.value, pLanguage ?? nullptr, pValue, pValueSize);
        if (err != BiosealError.success.value) {
          throw BiosealException(err);
        }
      }
      final vValue = utf8.decode(Uint8List.fromList(pValue.cast<Uint8>().asTypedList(pValueSize.value)));
      return vValue;
    } finally {
      if (pLanguage != null) {
        calloc.free(pLanguage);
      }
      calloc.free(pValue);
      calloc.free(pValueSize);
    }
  }

}

class FieldIterator implements Iterator<Field> {
  FieldIterator(this._list)
      : _count = _list.getCount(),
        _keys = [] {
    final StringArray keys = _list.getKeys();
    for (var key in keys) {
      _keys.add(key);
    }
    keys.dispose();
  }
  final Field _list;
  final int _count;
  int _index = -1;
  final List<String> _keys;

  @override
  Field get current => _list.get(_keys[_index]);

  @override
  bool moveNext() {
    _index++;
    return _index < _count;
  }
}
