// 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/widgets.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({ bool extraPadding, String text, ScrollController controller }) {
  return MaterialApp(
    home: Scaffold(
      body: Column(
        children: <Widget>[
          Expanded(
            child: Container(),
          ),
          Container(
            height: 500.0,
            child: ListView(
              controller: controller,
              children: List<Widget>.generate(10, (int i) {
                return Container(
                  color: i % 2 == 0 ? 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, this.extraPadding, 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;
}
