// 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.

// @dart = 2.8

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

int globalGeneration = 0;

class GenerationText extends StatefulWidget {
  const GenerationText(this.value, { Key key }) : super(key: key);
  final int value;
  @override
  _GenerationTextState createState() => _GenerationTextState();
}

class _GenerationTextState extends State<GenerationText> {
  _GenerationTextState() : generation = globalGeneration;
  final int generation;
  @override
  Widget build(BuildContext context) => Text('${widget.value}:$generation ', textDirection: TextDirection.ltr);
}

// Creates a SliverList with `keys.length` children and each child having a key from `keys` and a text of `key:generation`.
// The generation is increased with every call to this method.
Future<void> test(WidgetTester tester, double offset, List<int> keys) {
  globalGeneration += 1;
  return tester.pumpWidget(
    Directionality(
      textDirection: TextDirection.ltr,
      child: Viewport(
        cacheExtent: 0.0,
        offset: ViewportOffset.fixed(offset),
        slivers: <Widget>[
          SliverList(
            delegate: SliverChildListDelegate(keys.map<Widget>((int key) {
              return SizedBox(key: GlobalObjectKey(key), height: 100.0, child: GenerationText(key));
            }).toList()),
          ),
        ],
      ),
    ),
  );
}

// `answerKey`: Expected offsets of visible SliverList children in global coordinate system.
// `text`: A space-separated list of expected `key:generation` pairs for the visible SliverList children.
void verify(WidgetTester tester, List<Offset> answerKey, String text) {
  final List<Offset> testAnswers = tester.renderObjectList<RenderBox>(find.byType(SizedBox)).map<Offset>(
    (RenderBox target) => target.localToGlobal(const Offset(0.0, 0.0))
  ).toList();
  expect(testAnswers, equals(answerKey));
  final String foundText =
    tester.widgetList<Text>(find.byType(Text))
        .map<String>((Text widget) => widget.data)
        .reduce((String value, String element) => value + element);
  expect(foundText, equals(text));
}

void main() {
  testWidgets('Viewport+SliverBlock with GlobalKey reparenting', (WidgetTester tester) async {
    await test(tester, 0.0, <int>[1,2,3,4,5,6,7,8,9]);
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
    ], '1:1 2:1 3:1 4:1 5:1 6:1 ');
    // gen 2 - flipping the order:
    await test(tester, 0.0, <int>[9,8,7,6,5,4,3,2,1]);
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
    ], '9:2 8:2 7:2 6:1 5:1 4:1 ');
    // gen 3 - flipping the order back:
    await test(tester, 0.0, <int>[1,2,3,4,5,6,7,8,9]);
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
    ], '1:3 2:3 3:3 4:1 5:1 6:1 ');
    // gen 4 - removal:
    await test(tester, 0.0, <int>[1,2,3,5,6,7,8,9]);
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
    ], '1:3 2:3 3:3 5:1 6:1 7:4 ');
    // gen 5 - insertion:
    await test(tester, 0.0, <int>[1,2,3,4,5,6,7,8,9]);
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
    ], '1:3 2:3 3:3 4:5 5:1 6:1 ');
    // gen 6 - adjacent reordering:
    await test(tester, 0.0, <int>[1,2,3,5,4,6,7,8,9]);
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
    ], '1:3 2:3 3:3 5:1 4:5 6:1 ');
    // gen 7 - scrolling:
    await test(tester, 120.0, <int>[1,2,3,5,4,6,7,8,9]);
    verify(tester, <Offset>[
      const Offset(0.0, -20.0),
      const Offset(0.0, 80.0),
      const Offset(0.0, 180.0),
      const Offset(0.0, 280.0),
      const Offset(0.0, 380.0),
      const Offset(0.0, 480.0),
      const Offset(0.0, 580.0),
    ], '2:3 3:3 5:1 4:5 6:1 7:7 8:7 ');
  });
}
