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

/// Represents a date/time.
class DateTime implements Finalizable {
  /// Native handle.
  late Pointer<Pointer<id3BiosealDateTime>> _pHandle;
  bool _disposable = true;

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

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

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

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


  ///
  /// The year (1 through 9999, 0 if invalid date).
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get year => getYear();

  ///
  /// The month (1 through 12).
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get month => getMonth();

  ///
  /// The day (1 through the number of days in month).
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get day => getDay();

  ///
  /// The hour (0 through 23, -1 if invalid time).
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get hour => getHour();

  ///
  /// The minute (0 through 59).
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get minute => getMinute();

  ///
  /// The second (0 through 59).
  ///
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int get second => getSecond();

  // Public methods
  /// Gets the the year (1 through 9999, 0 if invalid date).
  ///
  /// return The year (1 through 9999, 0 if invalid date).
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getYear() {
    Pointer<Int> pYear = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_GetYear(_pHandle.value, pYear);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vYear = pYear.value;
      return vYear;
    } finally {
      calloc.free(pYear);
    }
  }

  /// Gets the the month (1 through 12).
  ///
  /// return The month (1 through 12).
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getMonth() {
    Pointer<Int> pMonth = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_GetMonth(_pHandle.value, pMonth);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vMonth = pMonth.value;
      return vMonth;
    } finally {
      calloc.free(pMonth);
    }
  }

  /// Gets the the day (1 through the number of days in month).
  ///
  /// return The day (1 through the number of days in month).
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getDay() {
    Pointer<Int> pDay = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_GetDay(_pHandle.value, pDay);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vDay = pDay.value;
      return vDay;
    } finally {
      calloc.free(pDay);
    }
  }

  /// Gets the the hour (0 through 23, -1 if invalid time).
  ///
  /// return The hour (0 through 23, -1 if invalid time).
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getHour() {
    Pointer<Int> pHour = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_GetHour(_pHandle.value, pHour);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vHour = pHour.value;
      return vHour;
    } finally {
      calloc.free(pHour);
    }
  }

  /// Gets the the minute (0 through 59).
  ///
  /// return The minute (0 through 59).
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getMinute() {
    Pointer<Int> pMinute = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_GetMinute(_pHandle.value, pMinute);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vMinute = pMinute.value;
      return vMinute;
    } finally {
      calloc.free(pMinute);
    }
  }

  /// Gets the the second (0 through 59).
  ///
  /// return The second (0 through 59).
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  int getSecond() {
    Pointer<Int> pSecond = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_GetSecond(_pHandle.value, pSecond);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vSecond = pSecond.value;
      return vSecond;
    } finally {
      calloc.free(pSecond);
    }
  }

  /// Indicates whether the date and/or time is valid.
  ///
  /// return true if date and/or time is valid.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool isValid() {
    Pointer<Bool> pResult = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_IsValid(_pHandle.value, pResult);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vResult = pResult.value;
      return vResult;
    } finally {
      calloc.free(pResult);
    }
  }

  /// Indicates whether the time is valid.
  ///
  /// return true if the time is valid.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool isTimeValid() {
    Pointer<Bool> pResult = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_IsTimeValid(_pHandle.value, pResult);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vResult = pResult.value;
      return vResult;
    } finally {
      calloc.free(pResult);
    }
  }

  /// Indicates whether the date is valid.
  ///
  /// return true if the date is valid.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool isDateValid() {
    Pointer<Bool> pResult = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_IsDateValid(_pHandle.value, pResult);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vResult = pResult.value;
      return vResult;
    } finally {
      calloc.free(pResult);
    }
  }

  /// Indicates whether the date and time are valid.
  ///
  /// return true if date and time is valid.
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  bool isDateTimeValid() {
    Pointer<Bool> pResult = calloc();
    try {
      var err = biosealSDK.id3BiosealDateTime_IsDateTimeValid(_pHandle.value, pResult);
      if (err != BiosealError.success.value) {
        throw BiosealException(err);
      }
      final vResult = pResult.value;
      return vResult;
    } finally {
      calloc.free(pResult);
    }
  }

  /// Convert the date/time to a string.
  ///
  /// return Automatic format is YYYY-MM-DDTHH:MM:SS, YYYY-MM-DD or HH:MM:SS
  /// throws BiosealException An error has occurred during Bioseal Library execution.
  String toString() {
    Pointer<Char> pResult = nullptr;
    Pointer<Int> pResultSize = calloc.allocate(1);
    pResultSize[0] = -1;
    try {
      var err = biosealSDK.id3BiosealDateTime_ToString(_pHandle.value, pResult, pResultSize);
      if (err == BiosealError.insufficientBuffer.value) {
        pResult = calloc.allocate(pResultSize.value);
        err = biosealSDK.id3BiosealDateTime_ToString(_pHandle.value, pResult, pResultSize);
        if (err != BiosealError.success.value) {
          throw BiosealException(err);
        }
      }
      final vResult = utf8.decode(Uint8List.fromList(pResult.cast<Uint8>().asTypedList(pResultSize.value)));
      return vResult;
    } finally {
      calloc.free(pResult);
      calloc.free(pResultSize);
    }
  }

}

