//--------------------------------------------------------------------------------------------------
// 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.id3BiosealLogItem_Dispose.cast());

/// Represents a log item.
class LogItem implements Finalizable {
  /// Native handle.
  late Pointer<Pointer<id3BiosealLogItem>> _pHandle;
  bool _disposable = true;

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

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

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

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


  ///
  /// The timestamp of the message.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get timestamp => getTimestamp();

  ///
  /// The log message.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String get message => getMessage();

  ///
  /// The log type.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  LogItemType get itemType => getItemType();

  ///
  /// The log item error code if any.
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  BiosealError get errorCode => getErrorCode();

  // Public methods
  /// Gets the the timestamp of the message.
  ///
  /// return The timestamp of the message.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getTimestamp() {
    Pointer<LongLong> pTimestamp = calloc();
    try {
      var err = biosealSDK.id3BiosealLogItem_GetTimestamp(_pHandle.value, pTimestamp);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vTimestamp = pTimestamp.value;
      return vTimestamp;
    } finally {
      calloc.free(pTimestamp);
    }
  }

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

  /// Gets the the log type.
  ///
  /// return The log type.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  LogItemType getItemType() {
    Pointer<Int32> pItemType = calloc();
    try {
      var err = biosealSDK.id3BiosealLogItem_GetItemType(_pHandle.value, pItemType);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vItemType = LogItemTypeX.fromValue(pItemType.value);
      return vItemType;
    } finally {
      calloc.free(pItemType);
    }
  }

  /// Gets the the log item error code if any.
  ///
  /// return The log item error code if any.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  BiosealError getErrorCode() {
    Pointer<Int32> pErrorCode = calloc();
    try {
      var err = biosealSDK.id3BiosealLogItem_GetErrorCode(_pHandle.value, pErrorCode);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vErrorCode = BiosealErrorX.fromValue(pErrorCode.value);
      return vErrorCode;
    } finally {
      calloc.free(pErrorCode);
    }
  }

}

