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

import 'dart:ffi';

import 'package:ffi/ffi.dart';

import 'objective_c_bindings_generated.dart' as objc;

Pointer<objc.ObjCSelector> registerName(String name) {
  final cstr = name.toNativeUtf8();
  final sel = objc.registerName(cstr.cast());
  calloc.free(cstr);
  return sel;
}

Pointer<objc.ObjCObject> getClass(String name) {
  final cstr = name.toNativeUtf8();
  final clazz = objc.getClass(cstr.cast());
  calloc.free(cstr);
  if (clazz == nullptr) {
    throw Exception('Failed to load Objective-C class: $name');
  }
  return clazz;
}

final msgSendPointer =
    Native.addressOf<NativeFunction<Void Function()>>(objc.msgSend);
final msgSendFpretPointer =
    Native.addressOf<NativeFunction<Void Function()>>(objc.msgSendFpret);
final msgSendStretPointer =
    Native.addressOf<NativeFunction<Void Function()>>(objc.msgSendStret);

final useMsgSendVariants =
    Abi.current() == Abi.iosX64 || Abi.current() == Abi.macosX64;

class _ObjCFinalizable<T extends NativeType> implements Finalizable {
  final Pointer<T> _ptr;
  bool _pendingRelease;

  _ObjCFinalizable(this._ptr, {required bool retain, required bool release})
      : _pendingRelease = release {
    if (retain) {
      _retain(_ptr.cast());
    }
    if (release) {
      _finalizer.attach(this, _ptr.cast(), detach: this);
    }
  }

  /// Releases the reference to the underlying ObjC object held by this wrapper.
  /// Throws a StateError if this wrapper doesn't currently hold a reference.
  void release() {
    if (_pendingRelease) {
      _pendingRelease = false;
      _release(_ptr.cast());
      _finalizer.detach(this);
    } else {
      throw StateError(
          'Released an ObjC object that was unowned or already released.');
    }
  }

  @override
  bool operator ==(Object other) {
    return other is _ObjCFinalizable && _ptr == other._ptr;
  }

  @override
  int get hashCode => _ptr.hashCode;

  /// Return a pointer to this object.
  Pointer<T> get pointer => _ptr;

  /// Retain a reference to this object and then return the pointer. This
  /// reference must be released when you are done with it. If you wrap this
  /// reference in another object, make sure to release it but not retain it:
  /// `castFromPointer(lib, pointer, retain: false, release: true)`
  Pointer<T> retainAndReturnPointer() {
    _retain(_ptr.cast());
    return _ptr;
  }

  NativeFinalizer get _finalizer => throw UnimplementedError();
  void _retain(Pointer<T> ptr) => throw UnimplementedError();
  void _release(Pointer<T> ptr) => throw UnimplementedError();
}

class ObjCObjectBase extends _ObjCFinalizable<objc.ObjCObject> {
  ObjCObjectBase(super.ptr, {required super.retain, required super.release});

  static final _objectFinalizer = NativeFinalizer(
      Native.addressOf<NativeFunction<Void Function(Pointer<objc.ObjCObject>)>>(
              objc.objectRelease)
          .cast());

  @override
  NativeFinalizer get _finalizer => _objectFinalizer;

  @override
  void _retain(Pointer<objc.ObjCObject> ptr) => objc.objectRetain(ptr);

  @override
  void _release(Pointer<objc.ObjCObject> ptr) => objc.objectRelease(ptr);
}

class ObjCBlockBase extends _ObjCFinalizable<objc.ObjCBlock> {
  ObjCBlockBase(super.ptr, {required super.retain, required super.release});

  static final _blockFinalizer = NativeFinalizer(
      Native.addressOf<NativeFunction<Void Function(Pointer<objc.ObjCBlock>)>>(
              objc.blockRelease)
          .cast());

  @override
  NativeFinalizer get _finalizer => _blockFinalizer;

  @override
  void _retain(Pointer<objc.ObjCBlock> ptr) => objc.blockCopy(ptr);

  @override
  void _release(Pointer<objc.ObjCBlock> ptr) => objc.blockRelease(ptr);
}

Pointer<objc.ObjCBlockDesc> _newBlockDesc() {
  final desc =
      calloc.allocate<objc.ObjCBlockDesc>(sizeOf<objc.ObjCBlockDesc>());
  desc.ref.reserved = 0;
  desc.ref.size = sizeOf<objc.ObjCBlock>();
  desc.ref.copy_helper = nullptr;
  desc.ref.dispose_helper = nullptr;
  desc.ref.signature = nullptr;
  return desc;
}

final _blockDesc = _newBlockDesc();

Pointer<objc.ObjCBlock> newBlock(Pointer<Void> invoke, Pointer<Void> target) {
  final b = calloc.allocate<objc.ObjCBlock>(sizeOf<objc.ObjCBlock>());
  b.ref.isa = objc.NSConcreteGlobalBlock;
  b.ref.flags = 0;
  b.ref.reserved = 0;
  b.ref.invoke = invoke;
  b.ref.target = target;
  b.ref.descriptor = _blockDesc;
  final copy = objc.blockCopy(b.cast()).cast<objc.ObjCBlock>();
  calloc.free(b);
  return copy;
}
