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

void main() {
  testWidgets('Render and element tree stay in sync when keyed children move around', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/48855.

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Column(
          children: const <Widget>[
            Text('0', key: ValueKey<int>(0)),
            Text('1', key: ValueKey<int>(1)),
            Text('2', key: ValueKey<int>(2)),
            Text('3', key: ValueKey<int>(3)),
            Text('4', key: ValueKey<int>(4)),
            Text('5', key: ValueKey<int>(5)),
            Text('6', key: ValueKey<int>(6)),
            Text('7', key: ValueKey<int>(7)),
            Text('8', key: ValueKey<int>(8)),
          ],
        ),
      ),
    );

    expect(
      _getChildOrder(tester.renderObject<RenderFlex>(find.byType(Column))),
      <String>['0', '1', '2', '3', '4', '5', '6', '7', '8'],
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Column(
          children: const <Widget>[
            Text('0', key: ValueKey<int>(0)),
            Text('6', key: ValueKey<int>(6)),
            Text('7', key: ValueKey<int>(7)),
            Text('8', key: ValueKey<int>(8)),
            Text('1', key: ValueKey<int>(1)),
            Text('2', key: ValueKey<int>(2)),
            Text('3', key: ValueKey<int>(3)),
            Text('4', key: ValueKey<int>(4)),
            Text('5', key: ValueKey<int>(5)),
          ],
        ),
      ),
    );

    expect(
      _getChildOrder(tester.renderObject<RenderFlex>(find.byType(Column))),
      <String>['0', '6', '7', '8', '1', '2', '3', '4', '5'],
    );
  });

  testWidgets('Building a new MultiChildRenderObjectElement with children having duplicated keys throws', (WidgetTester tester) async {
    const ValueKey<int> duplicatedKey = ValueKey<int>(1);

    await tester.pumpWidget(Column(
      children: const <Widget>[
        Text('Text 1', textDirection: TextDirection.ltr, key: duplicatedKey),
        Text('Text 2', textDirection: TextDirection.ltr, key: duplicatedKey),
      ],
    ));

    expect(
      tester.takeException(),
      isA<FlutterError>().having(
        (FlutterError error) => error.message,
        'error.message',
        startsWith('Duplicate keys found.'),
      ),
    );
  });

  testWidgets('Updating a MultiChildRenderObjectElement to have children with duplicated keys throws', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/81541

    const ValueKey<int> key1 = ValueKey<int>(1);
    const ValueKey<int> key2 = ValueKey<int>(2);

    Future<void> _buildWithKey(Key key) {
      return tester.pumpWidget(Column(
        children: <Widget>[
          const Text('Text 1', textDirection: TextDirection.ltr, key: key1),
          Text('Text 2', textDirection: TextDirection.ltr, key: key),
        ],
      ));
    }

    // Initial build with two different keys.
    await _buildWithKey(key2);
    expect(tester.takeException(), isNull);

    // Subsequent build with duplicated keys.
    await _buildWithKey(key1);
    expect(
      tester.takeException(),
      isA<FlutterError>().having(
        (FlutterError error) => error.message,
        'error.message',
        startsWith('Duplicate keys found.'),
      ),
    );
  });
}

// Do not use tester.renderObjectList(find.byType(RenderParagraph). That returns
// the RenderObjects in the order of their associated RenderObjectWidgets. The
// point of this test is to assert the children order in the render tree, though.
List<String> _getChildOrder(RenderFlex flex) {
  final List<String> childOrder = <String>[];
  flex.visitChildren((RenderObject child) {
    childOrder.add(((child as RenderParagraph).text as TextSpan).text!);
  });
  return childOrder;
}
