// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';

int _creations = 0;
int _disposals = 0;

void main() {
  // LeakTesting is turned off because it adds subscriptions to
  // [FlutterMemoryAllocations], that may interfere with the tests.
  LeakTesting.settings = LeakTesting.settings.withIgnoredAll();

  final FlutterMemoryAllocations ma = FlutterMemoryAllocations.instance;

  test('Publishers dispatch events in debug mode', () async {
    void listener(ObjectEvent event) {
      if (event is ObjectDisposed) {
        _disposals++;
      }
      if (event is ObjectCreated) {
        _creations++;
      }
    }
    ma.addListener(listener);

    final _EventStats actual = await _activateFlutterObjectsAndReturnCountOfEvents();
    expect(actual.creations, _creations);
    expect(actual.disposals, _disposals);

    ma.removeListener(listener);
    expect(ma.hasListeners, isFalse);
  });

  testWidgets('State dispatches events in debug mode', (WidgetTester tester) async {
    bool stateCreated = false;
    bool stateDisposed = false;

    expect(ma.hasListeners, false);

    void listener(ObjectEvent event) {
      if (event is ObjectCreated && event.object is State) {
        stateCreated = true;
      }
      if (event is ObjectDisposed && event.object is State) {
        stateDisposed = true;
      }
    }
    ma.addListener(listener);

    await tester.pumpWidget(const _TestStatefulWidget());
    expect(stateCreated, isTrue);
    expect(stateDisposed, isFalse);
    await tester.pumpWidget(const SizedBox.shrink());

    expect(stateCreated, isTrue);
    expect(stateDisposed, isTrue);
    ma.removeListener(listener);
    expect(ma.hasListeners, false);
  });
}

class _TestLeafRenderObjectWidget extends LeafRenderObjectWidget {
  @override
  RenderObject createRenderObject(BuildContext context) {
    return _TestRenderObject();
  }
}

class _TestElement extends RenderObjectElement with RootElementMixin {
  _TestElement(): super(_TestLeafRenderObjectWidget());

  void makeInactive() {
    final FocusManager newFocusManager = FocusManager();
    assignOwner(BuildOwner(focusManager: newFocusManager));
    mount(null, null);
    deactivate();
  }

  @override
  void insertRenderObjectChild(covariant RenderObject child, covariant Object? slot) { }

  @override
  void moveRenderObjectChild(covariant RenderObject child, covariant Object? oldSlot, covariant Object? newSlot) { }

  @override
  void removeRenderObjectChild(covariant RenderObject child, covariant Object? slot) { }
}

class _TestRenderObject extends RenderObject {
  @override
  void debugAssertDoesMeetConstraints() {}

  @override
  Rect get paintBounds => throw UnimplementedError();

  @override
  void performLayout() {}

  @override
  void performResize() {}

  @override
  Rect get semanticBounds => throw UnimplementedError();
}


class _TestStatefulWidget extends StatefulWidget {
  const _TestStatefulWidget();

  @override
  State<_TestStatefulWidget> createState() => _TestStatefulWidgetState();
}

class _TestStatefulWidgetState extends State<_TestStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}


class _EventStats {
  int creations = 0;
  int disposals = 0;
}

/// Create and dispose Flutter objects to fire memory allocation events.
Future<_EventStats> _activateFlutterObjectsAndReturnCountOfEvents() async {
  final _EventStats result = _EventStats();

  final _TestElement element = _TestElement(); result.creations++;
  final RenderObject renderObject = _TestRenderObject(); result.creations++;

  element.makeInactive(); result.creations += 4; // 1 for the new BuildOwner, 1 for the new FocusManager, 1 for the new FocusScopeNode, 1 for the new _HighlightModeManager
  element.unmount(); result.disposals += 2; // 1 for the old BuildOwner, 1 for the element
  renderObject.dispose(); result.disposals += 1;

  return result;
}
