// 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 'dart:async';

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

import 'restoration.dart';

void main() {
  final TestAutomatedTestWidgetsFlutterBinding binding = TestAutomatedTestWidgetsFlutterBinding();

  setUp(() {
    binding._restorationManager = MockRestorationManager();
  });

  testWidgets('does not inject root bucket if inside scope', (WidgetTester tester) async {
    final MockRestorationManager manager = MockRestorationManager();
    final Map<String, dynamic> rawData = <String, dynamic>{};
    final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
    expect(rawData, isEmpty);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: UnmanagedRestorationScope(
          bucket: root,
          child: const RootRestorationScope(
            restorationId: 'root-child',
            child: BucketSpy(
              child: Text('Hello'),
            ),
          ),
        ),
      ),
    );
    manager.doSerialization();

    expect(binding.restorationManager.rootBucketAccessed, 0);
    final BucketSpyState state = tester.state(find.byType(BucketSpy));
    expect(state.bucket!.restorationId, 'root-child');
    expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);

    expect(find.text('Hello'), findsOneWidget);
  });

  testWidgets('waits for root bucket', (WidgetTester tester) async {
    final Completer<RestorationBucket> bucketCompleter = Completer<RestorationBucket>();
    binding.restorationManager.rootBucket = bucketCompleter.future;

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          restorationId: 'root-child',
          child: BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    // Child rendering is delayed until root bucket is available.
    expect(find.text('Hello'), findsNothing);
    expect(binding.firstFrameIsDeferred, isTrue);

    // Complete the future.
    final Map<String, dynamic> rawData = <String, dynamic>{};
    final RestorationBucket root = RestorationBucket.root(manager: binding.restorationManager, rawData: rawData);
    bucketCompleter.complete(root);
    await tester.pump(const Duration(milliseconds: 100));

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    expect(binding.firstFrameIsDeferred, isFalse);

    final BucketSpyState state = tester.state(find.byType(BucketSpy));
    expect(state.bucket!.restorationId, 'root-child');
    expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
  });

  testWidgets('no delay when root is available synchronously', (WidgetTester tester) async {
    final Map<String, dynamic> rawData = <String, dynamic>{};
    final RestorationBucket root = RestorationBucket.root(manager: binding.restorationManager, rawData: rawData);
    binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket>(root);

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          restorationId: 'root-child',
          child: BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    expect(binding.firstFrameIsDeferred, isFalse);

    final BucketSpyState state = tester.state(find.byType(BucketSpy));
    expect(state.bucket!.restorationId, 'root-child');
    expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
  });

  testWidgets('does not insert root when restoration id is null', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          restorationId: null,
          child: BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 0);
    expect(find.text('Hello'), findsOneWidget);
    expect(binding.firstFrameIsDeferred, isFalse);

    final BucketSpyState state = tester.state(find.byType(BucketSpy));
    expect(state.bucket, isNull);

    // Change restoration id to non-null.
    final Completer<RestorationBucket> bucketCompleter = Completer<RestorationBucket>();
    binding.restorationManager.rootBucket = bucketCompleter.future;
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          restorationId: 'root-child',
          child: BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    expect(state.bucket, isNull); // root bucket future has not completed yet.

    // Complete the future.
    final RestorationBucket root = RestorationBucket.root(manager: binding.restorationManager, rawData: <String, dynamic>{});
    bucketCompleter.complete(root);
    await tester.pump(const Duration(milliseconds: 100));

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    expect(state.bucket!.restorationId, 'root-child');

    // Change ID back to null.
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          restorationId: null,
          child: BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    expect(state.bucket, isNull);
  });

  testWidgets('injects root bucket when moved out of scope', (WidgetTester tester) async {
    final Key rootScopeKey = GlobalKey();
    final MockRestorationManager manager = MockRestorationManager();
    final Map<String, dynamic> inScopeRawData = <String, dynamic>{};
    final RestorationBucket inScopeRootBucket = RestorationBucket.root(manager: manager, rawData: inScopeRawData);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: UnmanagedRestorationScope(
          bucket: inScopeRootBucket,
          child: RootRestorationScope(
            key: rootScopeKey,
            restorationId: 'root-child',
            child: const BucketSpy(
              child: Text('Hello'),
            ),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 0);
    expect(find.text('Hello'), findsOneWidget);
    final BucketSpyState state = tester.state(find.byType(BucketSpy));
    expect(state.bucket!.restorationId, 'root-child');
    expect((inScopeRawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);

    // Move out of scope.
    final Completer<RestorationBucket> bucketCompleter = Completer<RestorationBucket>();
    binding.restorationManager.rootBucket = bucketCompleter.future;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          key: rootScopeKey,
          restorationId: 'root-child',
          child: const BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);

    final Map<String, dynamic> outOfScopeRawData = <String, dynamic>{};
    final RestorationBucket outOfScopeRootBucket = RestorationBucket.root(manager: binding.restorationManager, rawData: outOfScopeRawData);
    bucketCompleter.complete(outOfScopeRootBucket);
    await tester.pump(const Duration(milliseconds: 100));

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    expect(state.bucket!.restorationId, 'root-child');
    expect((outOfScopeRawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
    expect(inScopeRawData, isEmpty);

    // Move into scope.
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: UnmanagedRestorationScope(
          bucket: inScopeRootBucket,
          child: RootRestorationScope(
            key: rootScopeKey,
            restorationId: 'root-child',
            child: const BucketSpy(
              child: Text('Hello'),
            ),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    expect(state.bucket!.restorationId, 'root-child');
    expect(outOfScopeRawData, isEmpty);
    expect((inScopeRawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
  });

  testWidgets('injects new root when old one is decommissioned', (WidgetTester tester) async {
    final Map<String, dynamic> firstRawData = <String, dynamic>{};
    final RestorationBucket firstRoot = RestorationBucket.root(manager: binding.restorationManager, rawData: firstRawData);
    binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket>(firstRoot);

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          restorationId: 'root-child',
          child: BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    final BucketSpyState state = tester.state(find.byType(BucketSpy));
    state.bucket!.write('foo', 42);
    expect((((firstRawData[childrenMapKey] as Map<Object?, Object?>)['root-child']! as Map<String, dynamic>)[valuesMapKey] as Map<Object?, Object?>)['foo'], 42);
    final RestorationBucket firstBucket = state.bucket!;

    // Replace with new root.
    final Map<String, dynamic> secondRawData = <String, dynamic>{
      childrenMapKey: <String, dynamic>{
        'root-child': <String, dynamic>{
          valuesMapKey: <String, dynamic>{
            'foo': 22,
          },
        },
      },
    };
    final RestorationBucket secondRoot = RestorationBucket.root(manager: binding.restorationManager, rawData: secondRawData);
    binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket>(secondRoot);
    await tester.pump();
    firstRoot.dispose();

    expect(state.bucket, isNot(same(firstBucket)));
    expect(state.bucket!.read<int>('foo'), 22);
  });

  testWidgets('injects null when rootBucket is null', (WidgetTester tester) async {
    final Completer<RestorationBucket?> completer = Completer<RestorationBucket?>();
    binding.restorationManager.rootBucket = completer.future;

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          restorationId: 'root-child',
          child: BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsNothing);

    completer.complete(null);
    await tester.pump(const Duration(milliseconds: 100));

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);

    final BucketSpyState state = tester.state(find.byType(BucketSpy));
    expect(state.bucket, isNull);

    final RestorationBucket root = RestorationBucket.root(manager: binding.restorationManager, rawData: null);
    binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket>(root);
    await tester.pump();

    expect(binding.restorationManager.rootBucketAccessed, 2);
    expect(find.text('Hello'), findsOneWidget);
    expect(state.bucket, isNotNull);
  });

  testWidgets('can switch to null', (WidgetTester tester) async {
    final RestorationBucket root = RestorationBucket.root(manager: binding.restorationManager, rawData: null);
    binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket>(root);

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: RootRestorationScope(
          restorationId: 'root-child',
          child: BucketSpy(
            child: Text('Hello'),
          ),
        ),
      ),
    );

    expect(binding.restorationManager.rootBucketAccessed, 1);
    expect(find.text('Hello'), findsOneWidget);
    final BucketSpyState state = tester.state(find.byType(BucketSpy));
    expect(state.bucket, isNotNull);

    binding.restorationManager.rootBucket = SynchronousFuture<RestorationBucket?>(null);
    await tester.pump();
    root.dispose();

    expect(binding.restorationManager.rootBucketAccessed, 2);
    expect(find.text('Hello'), findsOneWidget);
    expect(state.bucket, isNull);
  });
}

class TestAutomatedTestWidgetsFlutterBinding extends AutomatedTestWidgetsFlutterBinding {
  late MockRestorationManager _restorationManager;

  @override
  MockRestorationManager get restorationManager => _restorationManager;

  @override
  TestRestorationManager createRestorationManager() {
    return TestRestorationManager();
  }

  int _deferred = 0;

  bool get firstFrameIsDeferred => _deferred > 0;

  @override
  void deferFirstFrame() {
    _deferred++;
    super.deferFirstFrame();
  }

  @override
  void allowFirstFrame() {
    _deferred--;
    super.allowFirstFrame();
  }
}
