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

import 'semantics_tester.dart';

void main() {
  testWidgets('Un-layouted RenderObject in keep alive offstage area do not crash semantics compiler', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/20313.

    final SemanticsTester semantics = SemanticsTester(tester);

    const String initialLabel = 'Foo';
    const double bottomScrollOffset = 3000.0;

    final ScrollController controller = ScrollController(initialScrollOffset: bottomScrollOffset);

    await tester.pumpWidget(_buildTestWidget(
      extraPadding: false,
      text: initialLabel,
      controller: controller,
    ));
    await tester.pumpAndSettle();

    // The ProblemWidget has been instantiated (it is on screen).
    expect(tester.widgetList(find.widgetWithText(ProblemWidget, initialLabel)), hasLength(1));
    expect(semantics, includesNodeWith(label: initialLabel));

    controller.jumpTo(0.0);
    await tester.pumpAndSettle();

    // The ProblemWidget is not on screen...
    expect(tester.widgetList(find.widgetWithText(ProblemWidget, initialLabel)), hasLength(0));
    // ... but still in the tree as offstage.
    expect(tester.widgetList(find.widgetWithText(ProblemWidget, initialLabel, skipOffstage: false)), hasLength(1));
    expect(semantics, isNot(includesNodeWith(label: initialLabel)));

    // Introduce a new Padding widget to offstage subtree that will not get its
    // size calculated because it's offstage.
    await tester.pumpWidget(_buildTestWidget(
      extraPadding: true,
      text: initialLabel,
      controller: controller,
    ));
    final RenderPadding renderPadding = tester.renderObject(find.byKey(paddingWidget, skipOffstage: false));
    expect(renderPadding.hasSize, isFalse);
    expect(semantics, isNot(includesNodeWith(label: initialLabel)));

    // Change the semantics of the offstage ProblemWidget without crashing.
    const String newLabel = 'Bar';
    expect(newLabel, isNot(equals(initialLabel)));
    await tester.pumpWidget(_buildTestWidget(
      extraPadding: true,
      text: newLabel,
      controller: controller,
    ));

    // The label has changed.
    expect(tester.widgetList(find.widgetWithText(ProblemWidget, initialLabel, skipOffstage: false)), hasLength(0));
    expect(tester.widgetList(find.widgetWithText(ProblemWidget, newLabel, skipOffstage: false)), hasLength(1));
    expect(semantics, isNot(includesNodeWith(label: initialLabel)));
    expect(semantics, isNot(includesNodeWith(label: newLabel)));

    // Bringing the offstage node back on the screen produces correct semantics tree.
    controller.jumpTo(bottomScrollOffset);
    await tester.pumpAndSettle();

    expect(tester.widgetList(find.widgetWithText(ProblemWidget, initialLabel)), hasLength(0));
    expect(tester.widgetList(find.widgetWithText(ProblemWidget, newLabel)), hasLength(1));
    expect(semantics, isNot(includesNodeWith(label: initialLabel)));
    expect(semantics, includesNodeWith(label: newLabel));

    semantics.dispose();
  });
}

final Key paddingWidget = GlobalKey();

Widget _buildTestWidget({
  required bool extraPadding,
  required String text,
  required ScrollController controller,
}) {
  return MaterialApp(
    home: Scaffold(
      body: Column(
        children: <Widget>[
          Expanded(
            child: Container(),
          ),
          SizedBox(
            height: 500.0,
            child: ListView(
              controller: controller,
              children: List<Widget>.generate(10, (int i) {
                return Container(
                  color: i.isEven ? Colors.red : Colors.blue,
                  height: 250.0,
                  child: Text('Item $i'),
                );
              })..add(ProblemWidget(
                extraPadding: extraPadding,
                text: text,
              )),
            ),
          ),
          Expanded(
            child: Container(),
          ),
        ],
      ),
    ),
  );
}

class ProblemWidget extends StatefulWidget {
  const ProblemWidget({
    Key? key,
    required this.extraPadding,
    required this.text,
  }) : super(key: key);

  final bool extraPadding;
  final String text;

  @override
  State<ProblemWidget> createState() => ProblemWidgetState();
}

class ProblemWidgetState extends State<ProblemWidget> with AutomaticKeepAliveClientMixin<ProblemWidget> {
  @override
  Widget build(BuildContext context) {
    super.build(context);
    Widget child = Semantics(
      container: true,
      child: Text(widget.text),
    );
    if (widget.extraPadding) {
      child = Semantics(
        container: true,
        child: Padding(
          key: paddingWidget,
          padding: const EdgeInsets.all(20.0),
          child: child,
        ),
      );
    }
    return child;
  }

  @override
  bool get wantKeepAlive => true;
}
