// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// SharedObjects=ffi_test_functions

import 'dart:ffi';
import 'dart:isolate';

import 'package:ffi/ffi.dart';

import 'dylib_utils.dart';

void main() async {
  final myFinalizable2 = await Isolate.run(() => MyFinalizable());
  print(myFinalizable2);
  print(myFinalizable2.pointer);
  // This would crash if a NativeFinalizer would have been attached and run
  // eagerly on `Isolate.exit`.
  print(myFinalizable2.pointer.value);
}

@pragma('vm:deeply-immutable')
final class MyFinalizable implements Finalizable {
  final Pointer<Int> pointer;

  MyFinalizable._(this.pointer);

  factory MyFinalizable() {
    final pointer = calloc(sizeOf<Int>(), 10).cast<Int>();
    pointer.value = 123;
    final result = MyFinalizable._(pointer);
    newFinalizableHandle(
      result,
      pointer.cast(),
      0,
      freeFinalizer, // Not the signature of `free`!
    );
    return result;
  }
}

final calloc = dlopenPlatformSpecific("ffi_test_functions")
    .lookup<NativeFunction<Pointer<Void> Function(Size, Size)>>('Calloc')
    .asFunction<Pointer<Void> Function(int, int)>();

final freeFinalizer = dlopenPlatformSpecific(
  "ffi_test_functions",
).lookup<NativeFunction<Dart_HandleFinalizerFunction>>('FreeFinalizer');

final Dart_FinalizableHandle Function(
  Object,
  Pointer<Void>,
  int,
  Dart_HandleFinalizer,
)
newFinalizableHandle = _findDartApiFunction('Dart_NewFinalizableHandle')
    .cast<
      NativeFunction<
        Dart_FinalizableHandle Function(
          Handle,
          Pointer<Void>,
          IntPtr,
          Dart_HandleFinalizer,
        )
      >
    >()
    .asFunction();

final void Function(Dart_FinalizableHandle, Object) deleteFinalizableHandle =
    _findDartApiFunction('Dart_DeleteFinalizableHandle')
        .cast<NativeFunction<Void Function(Dart_FinalizableHandle, Handle)>>()
        .asFunction();

Pointer<Void> _findDartApiFunction(String name) {
  final dartApi = NativeApi.initializeApiDLData.cast<DartApi>();
  var entry = dartApi.ref.functions;
  while (true) {
    final entryName = entry.ref.name.cast<Utf8>().toDartString();
    if (entryName == name) {
      return entry.ref.function;
    }
    if (name == 'Dart_Null') {
      throw StateError('Dart API function with $name not found.');
    }
    entry++;
  }
}

final class DartApi extends Struct {
  @Int()
  external int major;

  @Int()
  external int minor;

  external Pointer<DartApiEntry> functions;
}

final class DartApiEntry extends Struct {
  external Pointer<Char> name;

  external Pointer<Void> function;
}

final class _Dart_FinalizableHandle extends Opaque {}

typedef Dart_HandleFinalizer =
    Pointer<NativeFunction<Dart_HandleFinalizerFunction>>;
typedef Dart_HandleFinalizerFunction =
    Void Function(Pointer<Void> isolate_callback_data, Pointer<Void> peer);
typedef DartDart_HandleFinalizerFunction =
    void Function(Pointer<Void> isolate_callback_data, Pointer<Void> peer);
typedef Dart_FinalizableHandle = Pointer<_Dart_FinalizableHandle>;
