// 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>;
