// Copyright (c) 2025, 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')
library;

import 'dart:ffi';

import 'package:objective_c/objective_c.dart';
import 'package:test/test.dart';

import 'util.dart';

void main() {
  group('Observer', () {
    test('receive updates', () {
      // Using NSProgress here because it's already part of our generated
      // bindings and has a property with a getter and setter.
      final observed = NSProgress();
      observed.totalUnitCount = 123;
      expect(observed.totalUnitCount, 123);

      final values = <dynamic>[];
      final observer = Observer$Builder.implement(
        observeValueForKeyPath_ofObject_change_context_:
            (
              NSString keyPath,
              ObjCObject object,
              NSDictionary change,
              Pointer<Void> context,
            ) {
              expect(keyPath.toDartString(), 'totalUnitCount');
              expect(object, observed);
              expect(context.address, 0x1234);
              values.add(
                toDartObject(change.asDart()[NSKeyValueChangeNewKey]!),
              );
            },
      );
      final observation = observed.addObserver(
        observer,
        forKeyPath: 'totalUnitCount'.toNSString(),
        context: Pointer<Void>.fromAddress(0x1234),
      );

      observed.totalUnitCount = 456;
      expect(values, [456]);

      observed.totalUnitCount = 789;
      expect(values, [456, 789]);

      observation.remove();

      observed.totalUnitCount = 246;
      expect(values, [456, 789]);

      observation.remove();

      observed.totalUnitCount = 999;
      expect(values, [456, 789]);
    });

    test('cancel observation due to GC', () {
      final observed = NSProgress();

      final values = <dynamic>[];
      final observer = Observer$Builder.implement(
        observeValueForKeyPath_ofObject_change_context_:
            (
              NSString keyPath,
              ObjCObject object,
              NSDictionary change,
              Pointer<Void> context,
            ) {
              values.add(
                toDartObject(change.asDart()[NSKeyValueChangeNewKey]!),
              );
            },
      );

      () {
        final observation = observed.addObserver(
          observer,
          forKeyPath: 'totalUnitCount'.toNSString(),
        );

        observed.totalUnitCount = 123;
        expect(values, [123]);

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

      doGC();

      observed.totalUnitCount = 456;
      expect(values, [123]);
    });

    test('observer and observed kept alive by observation', () async {
      final values = <dynamic>[];

      NSProgress? observed;
      Observer? observer;
      Observation? observation;
      autoReleasePool(() {
        observed = NSProgress();
        observer = Observer$Builder.implement(
          observeValueForKeyPath_ofObject_change_context_:
              (
                NSString keyPath,
                ObjCObject object,
                NSDictionary change,
                Pointer<Void> context,
              ) {
                values.add(
                  toDartObject(change.asDart()[NSKeyValueChangeNewKey]!),
                );

                // This is testing that a captured reference from the observer
                // to the observed object does not cause leak.
                expect(object, observed);
              },
        );

        observation = observed!.addObserver(
          observer!,
          forKeyPath: 'totalUnitCount'.toNSString(),
        );
      });

      observed!.totalUnitCount = 123;
      expect(values, [123]);

      final observedRaw = observed!.ref.pointer;
      final observerRaw = observer!.ref.pointer;

      observed = null;
      observer = null;

      // TODO(https://github.com/dart-lang/native/issues/2352): Reenable.
      // expect(objectRetainCount(observedRaw), greaterThan(0));
      // expect(objectRetainCount(observerRaw), greaterThan(0));

      NSProgress.fromPointer(observedRaw).totalUnitCount = 456;
      expect(values, [123, 456]);

      // Force observation to stay in scope.
      expect(observation, isNotNull);
      observation = null;
      expect(observation, isNull);

      doGC();
      await Future<void>.delayed(Duration.zero);
      doGC();

      expect(objectRetainCount(observedRaw), 0);
      expect(objectRetainCount(observerRaw), 0);
    });

    test('remove method drops references', () async {
      NSProgress? observed;
      Observer? observer;
      Observation? observation;
      autoReleasePool(() {
        observed = NSProgress();
        observer = Observer$Builder.implement(
          observeValueForKeyPath_ofObject_change_context_:
              (
                NSString keyPath,
                ObjCObject object,
                NSDictionary change,
                Pointer<Void> context,
              ) {},
        );

        observation = observed!.addObserver(
          observer!,
          forKeyPath: 'totalUnitCount'.toNSString(),
        );
      });

      final observedRaw = observed!.ref.pointer;
      final observerRaw = observer!.ref.pointer;

      observed = null;
      observer = null;

      doGC();
      await Future<void>.delayed(Duration.zero);
      doGC();

      // Still holding a reference to observation.
      // TODO(https://github.com/dart-lang/native/issues/2352): Reenable.
      // expect(objectRetainCount(observedRaw), greaterThan(0));
      // expect(objectRetainCount(observerRaw), greaterThan(0));

      observation!.remove();

      doGC();
      await Future<void>.delayed(Duration.zero);
      doGC();

      // Still holding a reference to observation, but we've called remove.
      expect(objectRetainCount(observedRaw), 0);
      expect(objectRetainCount(observerRaw), 0);

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