// 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/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('widget moves scopes during restore', (WidgetTester tester) async {
    await tester.pumpWidget(const RootRestorationScope(
      restorationId: 'root',
      child: Directionality(
        textDirection: TextDirection.ltr,
        child: TestWidgetWithCounterChild(),
      ),
    ));

    expect(tester.state<TestWidgetWithCounterChildState>(find.byType(TestWidgetWithCounterChild)).restoreChild, true);
    expect(find.text('Counter: 0'), findsOneWidget);
    await tester.tap(find.text('Counter: 0'));
    await tester.pump();
    expect(find.text('Counter: 1'), findsOneWidget);

    final TestRestorationData dataWithChild = await tester.getRestorationData();

    tester.state<TestWidgetWithCounterChildState>(find.byType(TestWidgetWithCounterChild)).restoreChild = false;
    await tester.pump();
    expect(tester.state<TestWidgetWithCounterChildState>(find.byType(TestWidgetWithCounterChild)).restoreChild, false);

    await tester.tap(find.text('Counter: 1'));
    await tester.pump();
    expect(find.text('Counter: 2'), findsOneWidget);

    final TestRestorationData dataWithoutChild = await tester.getRestorationData();

    // Child moves from outside to inside scope.
    await tester.restoreFrom(dataWithChild);
    expect(find.text('Counter: 1'), findsOneWidget);

    await tester.tap(find.text('Counter: 1'));
    await tester.pump();
    expect(find.text('Counter: 2'), findsOneWidget);

    // Child stays inside scope.
    await tester.restoreFrom(dataWithChild);
    expect(find.text('Counter: 1'), findsOneWidget);

    await tester.tap(find.text('Counter: 1'));
    await tester.tap(find.text('Counter: 1'));
    await tester.tap(find.text('Counter: 1'));
    await tester.tap(find.text('Counter: 1'));
    await tester.tap(find.text('Counter: 1'));
    await tester.pump();
    expect(find.text('Counter: 6'), findsOneWidget);

    // Child moves from inside to outside scope.
    await tester.restoreFrom(dataWithoutChild);
    expect(find.text('Counter: 6'), findsOneWidget);

    await tester.tap(find.text('Counter: 6'));
    await tester.pump();
    expect(find.text('Counter: 7'), findsOneWidget);

    // Child stays outside scope.
    await tester.restoreFrom(dataWithoutChild);
    expect(find.text('Counter: 7'), findsOneWidget);

    expect(tester.state<TestWidgetWithCounterChildState>(find.byType(TestWidgetWithCounterChild)).toggleCount, 0);
  });

  testWidgets('restoration is turned on later', (WidgetTester tester) async {
    tester.binding.restorationManager.disableRestoration();
    await tester.pumpWidget(const RootRestorationScope(
      restorationId: 'root-child',
      child: Directionality(
        textDirection: TextDirection.ltr,
        child: TestWidget(
          restorationId: 'foo',
        ),
      ),
    ));

    final TestWidgetState state = tester.state<TestWidgetState>(find.byType(TestWidget));
    expect(find.text('hello'), findsOneWidget);
    expect(state.buckets.single, isNull);
    expect(state.flags.single, isTrue);
    expect(state.bucket, isNull);

    state.buckets.clear();
    state.flags.clear();

    await tester.restoreFrom(TestRestorationData.empty);

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

    expect(find.text('hello'), findsOneWidget);
    expect(state.buckets.single, isNull);
    expect(state.flags.single, isFalse);
    expect(state.bucket, isNotNull);

    expect(state.toggleCount, 0);
  });
}

class TestWidgetWithCounterChild extends StatefulWidget {
  const TestWidgetWithCounterChild({Key? key}) : super(key: key);

  @override
  State<TestWidgetWithCounterChild> createState() => TestWidgetWithCounterChildState();
}

class TestWidgetWithCounterChildState extends State<TestWidgetWithCounterChild> with RestorationMixin {
  final RestorableBool childRestorationEnabled = RestorableBool(true);

  int toggleCount = 0;

  @override
  void didToggleBucket(RestorationBucket? oldBucket) {
    super.didToggleBucket(oldBucket);
    toggleCount++;
  }

  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    registerForRestoration(childRestorationEnabled, 'childRestorationEnabled');
  }

  bool get restoreChild => childRestorationEnabled.value;
  set restoreChild(bool value) {
    if (value == childRestorationEnabled.value) {
      return;
    }
    setState(() {
      childRestorationEnabled.value = value;
    });
  }

  @override
  void dispose() {
    childRestorationEnabled.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Counter(
      restorationId: restoreChild ? 'counter' : null,
    );
  }

  @override
  String get restorationId => 'foo';
}

class Counter extends StatefulWidget {
  const Counter({Key? key, this.restorationId}) : super(key: key);

  final String? restorationId;

  @override
  State<Counter> createState() => CounterState();
}

class CounterState extends State<Counter> with RestorationMixin {
  final RestorableInt count = RestorableInt(0);

  @override
  String? get restorationId => widget.restorationId;

  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    registerForRestoration(count, 'counter');
  }

  @override
  void dispose() {
    count.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return OutlinedButton(
      onPressed: () {
        setState(() {
          count.value++;
        });
      },
      child: Text(
        'Counter: ${count.value}',
      ),
    );
  }
}

class TestWidget extends StatefulWidget {
  const TestWidget({Key? key, required this.restorationId}) : super(key: key);

  final String? restorationId;

  @override
  State<TestWidget> createState() => TestWidgetState();
}

class TestWidgetState extends State<TestWidget> with RestorationMixin {
  List<RestorationBucket?> buckets = <RestorationBucket?>[];
  List<bool> flags = <bool>[];

  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    buckets.add(oldBucket);
    flags.add(initialRestore);
  }

  int toggleCount = 0;

  @override
  void didToggleBucket(RestorationBucket? oldBucket) {
    super.didToggleBucket(oldBucket);
    toggleCount++;
  }

  @override
  String? get restorationId => widget.restorationId;

  @override
  Widget build(BuildContext context) {
    return const Text('hello');
  }
}
