//--------------------------------------------------------------------------------------------------
// 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 'bioseal_sdk_generated_bindings.dart';
import 'bioseal_native.dart';

import '../id3_bioseal.dart';

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

/// Information about a certificate extension.
class CertificateExtension implements Finalizable {
  /// Native handle.
  late Pointer<Pointer<id3BiosealCertificateExtension>> _pHandle;
  bool _disposable = true;

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

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

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

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


  ///
  /// The OID of the certificate extension.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String get oid => getOid();

  ///
  /// A byte array that contains the value of the certificate extension.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Uint8List get value => getValue();

  ///
  /// A value indicating whether the certificate extension is critical.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool get critical => getCritical();

  // Public methods
  /// Gets the the OID of the certificate extension.
  ///
  /// return The OID of the certificate extension.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String getOid() {
    Pointer<Char> pOid = nullptr;
    Pointer<Int> pOidSize = calloc.allocate(1);
    pOidSize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealCertificateExtension_GetOid(_pHandle.value, pOid, pOidSize);
      if (err == BiosealError.insufficientBuffer.value) {
        pOid = calloc.allocate(pOidSize.value);
        err = biosealSDK.id3BiosealCertificateExtension_GetOid(_pHandle.value, pOid, pOidSize);
        if (err != BiosealError.success.value) {
          throw BiosealException(err);
        }
      }
      final vOid = utf8.decode(Uint8List.fromList(pOid.cast<Uint8>().asTypedList(pOidSize.value)));
      return vOid;
    } finally {
      calloc.free(pOid);
      calloc.free(pOidSize);
    }
  }

  /// Gets the A byte array that contains the value of the certificate extension.
  ///
  /// return A byte array that contains the value of the certificate extension.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  Uint8List getValue() {
    Pointer<UnsignedChar> pValue = nullptr;
    Pointer<Int> pValueSize = calloc();
    pValueSize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealCertificateExtension_GetValue(_pHandle.value, pValue, pValueSize);
      if (err == BiosealError.insufficientBuffer.value) {
        pValue = calloc.allocate(pValueSize.value);
        err = biosealSDK.id3BiosealCertificateExtension_GetValue(_pHandle.value, pValue, pValueSize);
      }
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vValue = Uint8List.fromList(pValue.cast<Uint8>().asTypedList(pValueSize.value));
      return vValue;
    } finally {
      calloc.free(pValue);
      calloc.free(pValueSize);
    }
  }

  /// Gets the A value indicating whether the certificate extension is critical.
  ///
  /// return A value indicating whether the certificate extension is critical.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool getCritical() {
    Pointer<Bool> pCritical = calloc();
    try {
      var err = biosealSDK.id3BiosealCertificateExtension_GetCritical(_pHandle.value, pCritical);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vCritical = pCritical.value;
      return vCritical;
    } finally {
      calloc.free(pCritical);
    }
  }

}

