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

// Objective C support is only available on mac.
@TestOn('mac-os')
import 'dart:async';
import 'dart:ffi';
import 'dart:io';
import 'dart:isolate';

import 'package:ffi/ffi.dart';
import 'package:objective_c/objective_c.dart' hide ObjCProtocolImpl;
import 'package:objective_c/src/internal.dart' show getProtocol;
import 'package:path/path.dart' as path;
import 'package:test/test.dart';

import '../test_utils.dart';
import 'protocol_test_bindings.dart';
import 'util.dart';

typedef InstanceMethodBlock = ObjCBlock_NSString_ffiVoid_NSString_ffiDouble;
typedef OptionalMethodBlock = ObjCBlock_Int32_ffiVoid_SomeStruct;
typedef VoidMethodBlock = ObjCBlock_ffiVoid_ffiVoid_Int32;
typedef OtherMethodBlock = ObjCBlock_Int32_ffiVoid_Int32_Int32_Int32_Int32;

void main() {
  late ProtocolTestObjCLibrary lib;

  group('protocol', () {
    setUpAll(() {
      final dylib = File(
        path.join(
          packagePathForTests,
          'test',
          'native_objc_test',
          'objc_test.dylib',
        ),
      );
      verifySetupFile(dylib);
      lib = ProtocolTestObjCLibrary(DynamicLibrary.open(dylib.absolute.path));
    });

    group('ObjC implementation', () {
      test('Method implementation', () {
        final protocolImpl = ObjCProtocolImpl();
        final MyProtocol asMyProtocol = protocolImpl;
        final SecondaryProtocol asSecondaryProtocol = protocolImpl;

        final consumer = ProtocolConsumer();

        // Required instance method.
        final result = consumer.callInstanceMethod(asMyProtocol);
        expect(
          result.toDartString(),
          'ObjCProtocolImpl: Hello from ObjC: 3.14',
        );

        // Optional instance method.
        final intResult = consumer.callOptionalMethod(asMyProtocol);
        expect(intResult, 579);

        // Required instance method from secondary protocol.
        final otherIntResult = consumer.callOtherMethod(asSecondaryProtocol);
        expect(otherIntResult, 10);

        // Method using two protocols.
        final twoMethodResult = consumer.callTwoMethods(asMyProtocol);
        expect(twoMethodResult, 579);
      });

      test('Method implementation, invoke from Dart', () {
        final protocolImpl = ObjCProtocolImpl();

        // Required instance method.
        final result = protocolImpl.instanceMethod(
          "abc".toNSString(),
          withDouble: 123,
        );
        expect(result.toDartString(), 'ObjCProtocolImpl: abc: 123.00');

        // Optional instance method.
        final structPtr = calloc<SomeStruct>();
        structPtr.ref.x = 12;
        structPtr.ref.y = 34;
        final intResult = protocolImpl.optionalMethod(structPtr.ref);
        expect(intResult, 46);
        calloc.free(structPtr);

        // Required instance method from secondary protocol.
        final otherIntResult = protocolImpl.otherMethod(2, b: 4, c: 6, d: 8);
        expect(otherIntResult, 20);

        // Method from a protocol that isn't included by the filters.
        expect(protocolImpl.fooMethod(), 2468);

        // Class methods.
        expect(ObjCProtocolImpl.requiredClassMethod(), 9876);
        expect(ObjCProtocolImpl.optionalClassMethod(), 5432);
      });

      test('Unimplemented method', () {
        final protocolImpl = ObjCProtocolImplMissingMethod();
        final consumer = ProtocolConsumer();

        // Optional instance method, not implemented.
        final intResult = consumer.callOptionalMethod(protocolImpl);
        expect(intResult, -999);
      });

      test('Unimplemented method, invoke from Dart', () {
        final protocolImpl = ObjCProtocolImplMissingMethod();

        // Optional instance method, not implemented.
        final structPtr = calloc<SomeStruct>();
        structPtr.ref.x = 12;
        structPtr.ref.y = 34;
        expect(
          () => protocolImpl.optionalMethod(structPtr.ref),
          throwsA(isA<UnimplementedOptionalMethodException>()),
        );
        calloc.free(structPtr);

        expect(
          () => ObjCProtocolImpl.unimplementedOtionalClassMethod(),
          throwsA(isA<UnimplementedOptionalMethodException>()),
        );
      });
    });

    group('Dart implementation using helpers', () {
      test('Method implementation', () {
        final consumer = ProtocolConsumer();

        final MyProtocol myProtocol = MyProtocol$Builder.implement(
          instanceMethod_withDouble_: (NSString s, double x) {
            return 'MyProtocol: ${s.toDartString()}: $x'.toNSString();
          },
          optionalMethod_: (SomeStruct s) {
            return s.y - s.x;
          },
        );

        expect(MyProtocol.conformsTo(myProtocol), isTrue);
        expect(SecondaryProtocol.conformsTo(myProtocol), isFalse);

        // Required instance method.
        final result = consumer.callInstanceMethod(myProtocol);
        expect(result.toDartString(), 'MyProtocol: Hello from ObjC: 3.14');

        // Optional instance method.
        final intResult = consumer.callOptionalMethod(myProtocol);
        expect(intResult, 333);
      });

      test('Multiple protocol implementation', () {
        final consumer = ProtocolConsumer();

        final protocolBuilder = ObjCProtocolBuilder();
        MyProtocol$Builder.addToBuilder(
          protocolBuilder,
          instanceMethod_withDouble_: (NSString s, double x) {
            return 'ProtocolBuilder: ${s.toDartString()}: $x'.toNSString();
          },
          optionalMethod_: (SomeStruct s) {
            return s.y - s.x;
          },
        );
        SecondaryProtocol$Builder.addToBuilder(
          protocolBuilder,
          otherMethod_b_c_d_: (int a, int b, int c, int d) {
            return a * b * c * d;
          },
        );
        final protocolImpl = protocolBuilder.build();
        final MyProtocol asMyProtocol = MyProtocol.as(protocolImpl);
        final SecondaryProtocol asSecondaryProtocol = SecondaryProtocol.as(
          protocolImpl,
        );

        expect(MyProtocol.conformsTo(protocolImpl), isTrue);
        expect(SecondaryProtocol.conformsTo(protocolImpl), isTrue);

        // Required instance method.
        final result = consumer.callInstanceMethod(asMyProtocol);
        expect(result.toDartString(), 'ProtocolBuilder: Hello from ObjC: 3.14');

        // Required instance method from secondary protocol.
        final otherIntResult = consumer.callOtherMethod(asSecondaryProtocol);
        expect(otherIntResult, 24);

        // Method using two protocols.
        final twoMethodResult = consumer.callTwoMethods(asMyProtocol);
        expect(twoMethodResult, 222000);
      });

      test('Multiple protocol implementation using method fields', () {
        final consumer = ProtocolConsumer();

        final protocolBuilder = ObjCProtocolBuilder();
        MyProtocol$Builder.instanceMethod_withDouble_.implement(
          protocolBuilder,
          (NSString s, double x) {
            return 'ProtocolBuilder: ${s.toDartString()}: $x'.toNSString();
          },
        );
        SecondaryProtocol$Builder.otherMethod_b_c_d_.implement(
          protocolBuilder,
          (int a, int b, int c, int d) {
            return a * b * c * d;
          },
        );
        final protocolImpl = protocolBuilder.build();
        final MyProtocol asMyProtocol = MyProtocol.as(protocolImpl);
        final SecondaryProtocol asSecondaryProtocol = SecondaryProtocol.as(
          protocolImpl,
        );

        // Required instance method.
        final result = consumer.callInstanceMethod(asMyProtocol);
        expect(result.toDartString(), 'ProtocolBuilder: Hello from ObjC: 3.14');

        // Required instance method from secondary protocol.
        final otherIntResult = consumer.callOtherMethod(asSecondaryProtocol);
        expect(otherIntResult, 24);
      });

      test('Unimplemented method', () {
        final consumer = ProtocolConsumer();

        final MyProtocol myProtocol = MyProtocol$Builder.implement(
          instanceMethod_withDouble_: (NSString s, double x) {
            throw UnimplementedError();
          },
        );

        // Optional instance method, not implemented.
        final intResult = consumer.callOptionalMethod(myProtocol);
        expect(intResult, -999);
      });

      test('Method implementation as listener', () async {
        final consumer = ProtocolConsumer();

        final listenerCompleter = Completer<int>();
        final MyProtocol myProtocol = MyProtocol$Builder.implementAsListener(
          instanceMethod_withDouble_: (NSString s, double x) {
            return 'MyProtocol: ${s.toDartString()}: $x'.toNSString();
          },
          optionalMethod_: (SomeStruct s) {
            return s.y - s.x;
          },
          voidMethod_: (int x) {
            listenerCompleter.complete(x);
          },
        );

        // Required instance method.
        final result = consumer.callInstanceMethod(myProtocol);
        expect(result.toDartString(), 'MyProtocol: Hello from ObjC: 3.14');

        // Optional instance method.
        final intResult = consumer.callOptionalMethod(myProtocol);
        expect(intResult, 333);

        // Listener method.
        consumer.callMethodOnRandomThread(myProtocol);
        expect(await listenerCompleter.future, 123);
      });

      test('Multiple protocol implementation as listener', () async {
        final consumer = ProtocolConsumer();

        final listenerCompleter = Completer<int>();
        final protocolBuilder = ObjCProtocolBuilder();
        MyProtocol$Builder.addToBuilderAsListener(
          protocolBuilder,
          instanceMethod_withDouble_: (NSString s, double x) {
            return 'ProtocolBuilder: ${s.toDartString()}: $x'.toNSString();
          },
          voidMethod_: (int x) {
            listenerCompleter.complete(x);
          },
        );
        SecondaryProtocol$Builder.addToBuilder(
          protocolBuilder,
          otherMethod_b_c_d_: (int a, int b, int c, int d) {
            return a * b * c * d;
          },
        );
        final protocolImpl = protocolBuilder.build();
        final MyProtocol asMyProtocol = MyProtocol.as(protocolImpl);
        final SecondaryProtocol asSecondaryProtocol = SecondaryProtocol.as(
          protocolImpl,
        );

        // Required instance method.
        final result = consumer.callInstanceMethod(asMyProtocol);
        expect(result.toDartString(), 'ProtocolBuilder: Hello from ObjC: 3.14');

        // Required instance method from secondary protocol.
        final otherIntResult = consumer.callOtherMethod(asSecondaryProtocol);
        expect(otherIntResult, 24);

        // Listener method.
        consumer.callMethodOnRandomThread(asMyProtocol);
        expect(await listenerCompleter.future, 123);
      });

      void waitSync(Duration d) {
        final t = Stopwatch();
        t.start();
        while (t.elapsed < d) {
          // Waiting...
        }
      }

      test('Method implementation as blocking', () async {
        final consumer = ProtocolConsumer();

        final listenerCompleter = Completer<int>();
        final MyProtocol myProtocol = MyProtocol$Builder.implementAsBlocking(
          instanceMethod_withDouble_: (NSString s, double x) {
            throw UnimplementedError();
          },
          voidMethod_: (int x) {
            listenerCompleter.complete(x);
          },
          intPtrMethod_: (Pointer<Int32> ptr) {
            waitSync(Duration(milliseconds: 100));
            ptr.value = 123456;
          },
        );

        // Blocking method.
        consumer.callBlockingMethodOnRandomThread(myProtocol);
        expect(await listenerCompleter.future, 123456);
      });

      test('Multiple protocol implementation as blocking', () async {
        final consumer = ProtocolConsumer();

        final listenerCompleter = Completer<int>();
        final protocolBuilder = ObjCProtocolBuilder();
        MyProtocol$Builder.addToBuilderAsBlocking(
          protocolBuilder,
          instanceMethod_withDouble_: (NSString s, double x) {
            throw UnimplementedError();
          },
          voidMethod_: (int x) {
            listenerCompleter.complete(x);
          },
          intPtrMethod_: (Pointer<Int32> ptr) {
            waitSync(Duration(milliseconds: 100));
            ptr.value = 98765;
          },
        );
        SecondaryProtocol$Builder.addToBuilder(
          protocolBuilder,
          otherMethod_b_c_d_: (int a, int b, int c, int d) {
            return a * b * c * d;
          },
        );
        final protocolImpl = protocolBuilder.build();
        final MyProtocol asMyProtocol = MyProtocol.as(protocolImpl);
        final SecondaryProtocol asSecondaryProtocol = SecondaryProtocol.as(
          protocolImpl,
        );

        // Required instance method from secondary protocol.
        final otherIntResult = consumer.callOtherMethod(asSecondaryProtocol);
        expect(otherIntResult, 24);

        // Blocking method.
        consumer.callBlockingMethodOnRandomThread(asMyProtocol);
        expect(await listenerCompleter.future, 98765);
      });

      test('Direct method implementation using block', () async {
        final consumer = ProtocolConsumer();

        final builder = ObjCProtocolBuilder();
        MyProtocol$Builder.instanceMethod_withDouble_.implementWithBlock(
          builder,
          ObjCBlock_NSString_ffiVoid_NSString_ffiDouble.fromFunction(
            (Pointer<Void> _, NSString s, double x) =>
                'DirectImpl: ${s.toDartString()}: $x'.toNSString(),
          ),
        );
        final myProtocol = MyProtocol.as(builder.build());

        // Required instance method.
        final result = consumer.callInstanceMethod(myProtocol);
        expect(result.toDartString(), 'DirectImpl: Hello from ObjC: 3.14');
      });
    });

    test('Filters', () {
      // SuperProtocol and FilteredProtocol's methods are included in the
      // bindings, but there should only be stub bindings for the protocols
      // themselves, because they're not included by the config.
      // FilteredUnusedProtocol shouldn't appear at all.
      final bindings = File(
        path.join(
          packagePathForTests,
          'test',
          'native_objc_test',
          'protocol_test_bindings.dart',
        ),
      ).readAsStringSync();

      expect(bindings, contains('instanceMethod_withDouble_'));
      expect(bindings, contains('fooMethod'));

      expect(bindings, contains('EmptyProtocol'));
      expect(bindings, isNot(contains('EmptyProtocol is a stub')));

      expect(bindings, contains('MyProtocol'));
      expect(bindings, isNot(contains('MyProtocol is a stub')));

      expect(bindings, contains('SecondaryProtocol'));
      expect(bindings, isNot(contains('SecondaryProtocol is a stub')));

      expect(bindings, contains('SuperProtocol is a stub'));

      expect(bindings, contains('FilteredProtocol is a stub'));

      expect(bindings, isNot(contains('FilteredUnusedProtocol')));
      expect(bindings, isNot(contains('filteredUnusedProtocolMethod')));
    });

    test('Unused protocol', () {
      // Regression test for https://github.com/dart-lang/native/issues/1672.
      final proto = UnusedProtocol$Builder.implement(someMethod: () => 123);
      expect(proto, isNotNull);
    });

    test('Disabled method', () {
      // Regression test for https://github.com/dart-lang/native/issues/1702.
      expect(MyProtocol$Builder.instanceMethod_withDouble_.isAvailable, isTrue);
      expect(MyProtocol$Builder.optionalMethod_.isAvailable, isTrue);
      expect(MyProtocol$Builder.disabledMethod.isAvailable, isFalse);

      expect(
        () => MyProtocol$Builder.disabledMethod.implement(
          ObjCProtocolBuilder(),
          () => 123,
        ),
        throwsA(isA<FailedToLoadProtocolMethodException>()),
      );
    });

    test('conformsTo', () {
      final inst = ObjCProtocolImpl();
      expect(NSObjectProtocol.conformsTo(inst), isTrue);
      expect(MyProtocol.conformsTo(inst), isTrue);
      expect(SecondaryProtocol.conformsTo(inst), isTrue);
      expect(EmptyProtocol.conformsTo(inst), isFalse);
      expect(UnusedProtocol.conformsTo(inst), isFalse);
    });

    test('Threading stress test', () async {
      final consumer = ProtocolConsumer();
      final completer = Completer<void>();
      int count = 0;

      final protocolBuilder = ObjCProtocolBuilder();
      MyProtocol$Builder.voidMethod_.implementAsListener(protocolBuilder, (
        int x,
      ) {
        expect(x, 123);
        ++count;
        if (count == 1000) completer.complete();
      });

      final protocol = protocolBuilder.build();
      final MyProtocol asMyProtocol = MyProtocol.as(protocol);

      for (int i = 0; i < 1000; ++i) {
        consumer.callMethodOnRandomThread(asMyProtocol);
      }
      await completer.future;
      expect(count, 1000);
    });

    (NSObject, Pointer<ObjCBlockImpl>) blockRefCountTestInner() {
      final pool = lib.objc_autoreleasePoolPush();
      final protocolBuilder = ObjCProtocolBuilder();

      final block = InstanceMethodBlock.fromFunction(
        (Pointer<Void> p, NSString s, double x) => 'Hello'.toNSString(),
      );
      MyProtocol$Builder.instanceMethod_withDouble_.implementWithBlock(
        protocolBuilder,
        block,
      );
      final protocol = protocolBuilder.build();
      lib.objc_autoreleasePoolPop(pool);

      final blockPtr = block.ref.pointer;

      // There are 2 references to the block. One owned by the Dart wrapper
      // object, and the other owned by the protocol.
      doGC();
      expect(blockRetainCount(blockPtr), 2);

      return (protocol, blockPtr);
    }

    Pointer<ObjCBlockImpl> blockRefCountTest() {
      final (protocol, blockPtr) = blockRefCountTestInner();

      // The Dart side block pointer has gone out of scope, but the protocol
      // still owns a reference to it.
      doGC();
      expect(blockRetainCount(blockPtr), 1);

      expect(protocol, isNotNull); // Force protocol to stay in scope.

      return blockPtr;
    }

    test('Block ref counting', () {
      final blockPtr = blockRefCountTest();

      // The protocol object has gone out of scope, so it should be cleaned up.
      // So should the block.
      doGC();
      expect(blockRetainCount(blockPtr), 0);
    }, skip: !canDoGC);

    test('keepIsolateAlive', () async {
      final isolateSendPort = Completer<SendPort>();
      final protosCreated = Completer<void>();
      final protoKeepAliveDestroyed = Completer<void>();
      final receivePort = RawReceivePort((msg) {
        if (msg is SendPort) {
          isolateSendPort.complete(msg);
        } else if (msg == 'Protocols created') {
          protosCreated.complete();
        } else if (msg == 'protoKeepAlive destroyed') {
          protoKeepAliveDestroyed.complete();
        }
      });

      final isExited = Completer<void>();
      late final RawReceivePort exitPort;
      exitPort = RawReceivePort((_) {
        isExited.complete();
        exitPort.close();
      });

      final isolate = Isolate.spawn(
        (sendPort) {
          final protoKeepAlive = ObjCProtocolBuilder().build(
            keepIsolateAlive: true,
          );
          final protoDontKeepAlive = ObjCProtocolBuilder().build(
            keepIsolateAlive: false,
          );
          sendPort.send('Protocols created');

          final isolatePort = RawReceivePort((msg) {
            if (msg == 'Destroy protoKeepAlive') {
              protoKeepAlive.ref.release();
              sendPort.send('protoKeepAlive destroyed');
            }
          })..keepIsolateAlive = false;

          sendPort.send(isolatePort.sendPort);
        },
        receivePort.sendPort,
        onExit: exitPort.sendPort,
      );

      await protosCreated.future;

      doGC();
      await Future<void>.delayed(Duration.zero); // Let dispose message arrive.
      doGC();
      await Future<void>.delayed(Duration.zero); // Let exit message arrive.

      // Both blocks are still alive.
      expect(isExited.isCompleted, isFalse);

      (await isolateSendPort.future).send('Destroy protoKeepAlive');
      await protoKeepAliveDestroyed.future;

      doGC();
      await Future<void>.delayed(Duration.zero); // Let dispose message arrive.
      doGC();
      await Future<void>.delayed(Duration.zero); // Let exit message arrive.

      // Only protoDontKeepAlive is alive.
      await isExited;

      receivePort.close();
    }, skip: !canDoGC);

    test('class disposal, builder first', () {
      final pool = lib.objc_autoreleasePoolPush();
      ObjCProtocolBuilder? protocolBuilder = ObjCProtocolBuilder(
        debugName: 'Foo',
      );

      NSObject? protocol = protocolBuilder.build();
      final clazz = lib.getClass(protocol);
      expect(
        lib.getClassName(clazz).cast<Utf8>().toDartString(),
        startsWith('Foo'),
      );
      expect(isValidClass(clazz), isTrue);
      lib.objc_autoreleasePoolPop(pool);

      protocolBuilder = null;
      doGC();
      expect(isValidClass(clazz), isTrue);

      protocol = null;
      doGC();
      expect(isValidClass(clazz), isFalse);
    }, skip: !canDoGC);

    test('class disposal, instance first', () {
      final pool = lib.objc_autoreleasePoolPush();
      ObjCProtocolBuilder? protocolBuilder = ObjCProtocolBuilder(
        debugName: 'Foo',
      );

      NSObject? protocol = protocolBuilder.build();
      final clazz = lib.getClass(protocol);
      expect(
        lib.getClassName(clazz).cast<Utf8>().toDartString(),
        startsWith('Foo'),
      );
      expect(isValidClass(clazz), isTrue);
      lib.objc_autoreleasePoolPop(pool);

      protocolBuilder = null;
      doGC();
      expect(isValidClass(clazz), isTrue);

      protocol = null;
      doGC();
      expect(isValidClass(clazz), isFalse);
    }, skip: !canDoGC);

    test('adding more methods after build', () {
      final protocolBuilder = ObjCProtocolBuilder();

      MyProtocol$Builder.addToBuilder(
        protocolBuilder,
        instanceMethod_withDouble_: (NSString s, double x) {
          return 'ProtocolBuilder: ${s.toDartString()}: $x'.toNSString();
        },
        optionalMethod_: (SomeStruct s) {
          return s.y - s.x;
        },
      );

      final protocolImpl = protocolBuilder.build();

      expect(
        () => SecondaryProtocol$Builder.addToBuilder(
          protocolBuilder,
          otherMethod_b_c_d_: (int a, int b, int c, int d) {
            return a * b * c * d;
          },
        ),
        throwsA(isA<StateError>()),
      );
    });

    test('calling methods on a protocol instance', () {
      final protoImpl = ObjCProtocolImpl();

      final MyProtocol myProto = protoImpl.returnsMyProtocol();
      final result = myProto.instanceMethod(
        "abc".toNSString(),
        withDouble: 123,
      );
      expect(result.toDartString(), 'ObjCProtocolImpl: abc: 123.00');
    });
  });
}
