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

void main() {
  testWidgets('Nested TickerMode cannot turn tickers back on', (WidgetTester tester) async {
    int outerTickCount = 0;
    int innerTickCount = 0;

    Widget nestedTickerModes({required bool innerEnabled, required bool outerEnabled}) {
      return Directionality(
        textDirection: TextDirection.rtl,
        child: TickerMode(
          enabled: outerEnabled,
          child: Row(
            children: <Widget>[
              _TickingWidget(
                onTick: () {
                  outerTickCount++;
                },
              ),
              TickerMode(
                enabled: innerEnabled,
                child: _TickingWidget(
                  onTick: () {
                    innerTickCount++;
                  },
                ),
              ),
            ],
          ),
        ),
      );
    }

    await tester.pumpWidget(
      nestedTickerModes(
        outerEnabled: false,
        innerEnabled: true,
      ),
    );

    expect(outerTickCount, 0);
    expect(innerTickCount, 0);
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(outerTickCount, 0);
    expect(innerTickCount, 0);

    await tester.pumpWidget(
      nestedTickerModes(
        outerEnabled: true,
        innerEnabled: false,
      ),
    );
    outerTickCount = 0;
    innerTickCount = 0;
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(outerTickCount, 4);
    expect(innerTickCount, 0);

    await tester.pumpWidget(
      nestedTickerModes(
        outerEnabled: true,
        innerEnabled: true,
      ),
    );
    outerTickCount = 0;
    innerTickCount = 0;
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(outerTickCount, 4);
    expect(innerTickCount, 4);

    await tester.pumpWidget(
      nestedTickerModes(
        outerEnabled: false,
        innerEnabled: false,
      ),
    );
    outerTickCount = 0;
    innerTickCount = 0;
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(outerTickCount, 0);
    expect(innerTickCount, 0);
  });

  testWidgets('Changing TickerMode does not rebuild widgets with SingleTickerProviderStateMixin', (WidgetTester tester) async {
    Widget widgetUnderTest({required bool tickerEnabled}) {
      return TickerMode(
        enabled: tickerEnabled,
        child: const _TickingWidget(),
      );
    }
    _TickingWidgetState state() => tester.state<_TickingWidgetState>(find.byType(_TickingWidget));

    await tester.pumpWidget(widgetUnderTest(tickerEnabled: true));
    expect(state().ticker.isTicking, isTrue);
    expect(state().buildCount, 1);

    await tester.pumpWidget(widgetUnderTest(tickerEnabled: false));
    expect(state().ticker.isTicking, isFalse);
    expect(state().buildCount, 1);

    await tester.pumpWidget(widgetUnderTest(tickerEnabled: true));
    expect(state().ticker.isTicking, isTrue);
    expect(state().buildCount, 1);
  });

  testWidgets('Changing TickerMode does not rebuild widgets with TickerProviderStateMixin', (WidgetTester tester) async {
    Widget widgetUnderTest({required bool tickerEnabled}) {
      return TickerMode(
        enabled: tickerEnabled,
        child: const _MultiTickingWidget(),
      );
    }
    _MultiTickingWidgetState state() => tester.state<_MultiTickingWidgetState>(find.byType(_MultiTickingWidget));

    await tester.pumpWidget(widgetUnderTest(tickerEnabled: true));
    expect(state().ticker.isTicking, isTrue);
    expect(state().buildCount, 1);

    await tester.pumpWidget(widgetUnderTest(tickerEnabled: false));
    expect(state().ticker.isTicking, isFalse);
    expect(state().buildCount, 1);

    await tester.pumpWidget(widgetUnderTest(tickerEnabled: true));
    expect(state().ticker.isTicking, isTrue);
    expect(state().buildCount, 1);
  });

  testWidgets('Moving widgets with SingleTickerProviderStateMixin to a new TickerMode ancestor works', (WidgetTester tester) async {
    final GlobalKey tickingWidgetKey = GlobalKey();
    Widget widgetUnderTest({required LocalKey tickerModeKey, required bool tickerEnabled}) {
      return TickerMode(
        key: tickerModeKey,
        enabled: tickerEnabled,
        child: _TickingWidget(key: tickingWidgetKey),
      );
    }
    // Using different local keys to simulate changing TickerMode ancestors.
    await tester.pumpWidget(widgetUnderTest(tickerEnabled: true, tickerModeKey: UniqueKey()));
    final State tickerModeState = tester.state(find.byType(TickerMode));
    final _TickingWidgetState tickingState = tester.state<_TickingWidgetState>(find.byType(_TickingWidget));
    expect(tickingState.ticker.isTicking, isTrue);

    await tester.pumpWidget(widgetUnderTest(tickerEnabled: false, tickerModeKey: UniqueKey()));
    expect(tester.state(find.byType(TickerMode)), isNot(same(tickerModeState)));
    expect(tickingState, same(tester.state<_TickingWidgetState>(find.byType(_TickingWidget))));
    expect(tickingState.ticker.isTicking, isFalse);
  });

  testWidgets('Moving widgets with TickerProviderStateMixin to a new TickerMode ancestor works', (WidgetTester tester) async {
    final GlobalKey tickingWidgetKey = GlobalKey();
    Widget widgetUnderTest({required LocalKey tickerModeKey, required bool tickerEnabled}) {
      return TickerMode(
        key: tickerModeKey,
        enabled: tickerEnabled,
        child: _MultiTickingWidget(key: tickingWidgetKey),
      );
    }
    // Using different local keys to simulate changing TickerMode ancestors.
    await tester.pumpWidget(widgetUnderTest(tickerEnabled: true, tickerModeKey: UniqueKey()));
    final State tickerModeState = tester.state(find.byType(TickerMode));
    final _MultiTickingWidgetState tickingState = tester.state<_MultiTickingWidgetState>(find.byType(_MultiTickingWidget));
    expect(tickingState.ticker.isTicking, isTrue);

    await tester.pumpWidget(widgetUnderTest(tickerEnabled: false, tickerModeKey: UniqueKey()));
    expect(tester.state(find.byType(TickerMode)), isNot(same(tickerModeState)));
    expect(tickingState, same(tester.state<_MultiTickingWidgetState>(find.byType(_MultiTickingWidget))));
    expect(tickingState.ticker.isTicking, isFalse);
  });

  testWidgets('Ticking widgets in old route do not rebuild when new route is pushed', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      routes: <String, WidgetBuilder>{
        '/foo' : (BuildContext context) => const Text('New route'),
      },
      home: Row(
        children: const <Widget>[
          _TickingWidget(),
          _MultiTickingWidget(),
          Text('Old route'),
        ],
      ),
    ));

    _MultiTickingWidgetState multiTickingState() => tester.state<_MultiTickingWidgetState>(find.byType(_MultiTickingWidget, skipOffstage: false));
    _TickingWidgetState tickingState() => tester.state<_TickingWidgetState>(find.byType(_TickingWidget, skipOffstage: false));

    expect(find.text('Old route'), findsOneWidget);
    expect(find.text('New route'), findsNothing);

    expect(multiTickingState().ticker.isTicking, isTrue);
    expect(multiTickingState().buildCount, 1);
    expect(tickingState().ticker.isTicking, isTrue);
    expect(tickingState().buildCount, 1);

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/foo');
    await tester.pumpAndSettle();
    expect(find.text('Old route'), findsNothing);
    expect(find.text('New route'), findsOneWidget);

    expect(multiTickingState().ticker.isTicking, isFalse);
    expect(multiTickingState().buildCount, 1);
    expect(tickingState().ticker.isTicking, isFalse);
    expect(tickingState().buildCount, 1);
  });
}

class _TickingWidget extends StatefulWidget {
  const _TickingWidget({super.key, this.onTick});

  final VoidCallback? onTick;

  @override
  State<_TickingWidget> createState() => _TickingWidgetState();
}

class _TickingWidgetState extends State<_TickingWidget> with SingleTickerProviderStateMixin {
  late Ticker ticker;
  int buildCount = 0;

  @override
  void initState() {
    super.initState();
    ticker = createTicker((Duration _) {
      widget.onTick?.call();
    })..start();
  }

  @override
  Widget build(BuildContext context) {
    buildCount += 1;
    return Container();
  }

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

class _MultiTickingWidget extends StatefulWidget {
  const _MultiTickingWidget({super.key});

  @override
  State<_MultiTickingWidget> createState() => _MultiTickingWidgetState();
}

class _MultiTickingWidgetState extends State<_MultiTickingWidget> with TickerProviderStateMixin {
  late Ticker ticker;
  int buildCount = 0;

  @override
  void initState() {
    super.initState();
    ticker = createTicker((Duration _) {
    })..start();
  }

  @override
  Widget build(BuildContext context) {
    buildCount += 1;
    return Container();
  }

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