// Copyright 2016 The Chromium 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_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);
  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 ');
  });
}
