// 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';

import 'test_widgets.dart';

class TestParentData {
  TestParentData({ this.top, this.right, this.bottom, this.left });

  final double top;
  final double right;
  final double bottom;
  final double left;
}

void checkTree(WidgetTester tester, List<TestParentData> expectedParentData) {
  final MultiChildRenderObjectElement element = tester.element(
    find.byElementPredicate((Element element) => element is MultiChildRenderObjectElement)
  );
  expect(element, isNotNull);
  expect(element.renderObject, isA<RenderStack>());
  final RenderStack renderObject = element.renderObject as RenderStack;
  try {
    RenderObject child = renderObject.firstChild;
    for (final TestParentData expected in expectedParentData) {
      expect(child, isA<RenderDecoratedBox>());
      final RenderDecoratedBox decoratedBox = child as RenderDecoratedBox;
      expect(decoratedBox.parentData, isA<StackParentData>());
      final StackParentData parentData = decoratedBox.parentData as StackParentData;
      expect(parentData.top, equals(expected.top));
      expect(parentData.right, equals(expected.right));
      expect(parentData.bottom, equals(expected.bottom));
      expect(parentData.left, equals(expected.left));
      final StackParentData decoratedBoxParentData = decoratedBox.parentData as StackParentData;
      child = decoratedBoxParentData.nextSibling;
    }
    expect(child, isNull);
  } catch (e) {
    print(renderObject.toStringDeep());
    rethrow;
  }
}

final TestParentData kNonPositioned = TestParentData();

void main() {
  testWidgets('ParentDataWidget control test', (WidgetTester tester) async {
    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: const <Widget>[
          DecoratedBox(decoration: kBoxDecorationA),
          Positioned(
            top: 10.0,
            left: 10.0,
            child: DecoratedBox(decoration: kBoxDecorationB),
          ),
          DecoratedBox(decoration: kBoxDecorationC),
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      kNonPositioned,
      TestParentData(top: 10.0, left: 10.0),
      kNonPositioned,
    ]);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: const <Widget>[
          Positioned(
            bottom: 5.0,
            right: 7.0,
            child: DecoratedBox(decoration: kBoxDecorationA),
          ),
          Positioned(
            top: 10.0,
            left: 10.0,
            child: DecoratedBox(decoration: kBoxDecorationB),
          ),
          DecoratedBox(decoration: kBoxDecorationC),
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      TestParentData(bottom: 5.0, right: 7.0),
      TestParentData(top: 10.0, left: 10.0),
      kNonPositioned,
    ]);

    const DecoratedBox kDecoratedBoxA = DecoratedBox(decoration: kBoxDecorationA);
    const DecoratedBox kDecoratedBoxB = DecoratedBox(decoration: kBoxDecorationB);
    const DecoratedBox kDecoratedBoxC = DecoratedBox(decoration: kBoxDecorationC);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: const <Widget>[
          Positioned(
            bottom: 5.0,
            right: 7.0,
            child: kDecoratedBoxA,
          ),
          Positioned(
            top: 10.0,
            left: 10.0,
            child: kDecoratedBoxB,
          ),
          kDecoratedBoxC,
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      TestParentData(bottom: 5.0, right: 7.0),
      TestParentData(top: 10.0, left: 10.0),
      kNonPositioned,
    ]);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: const <Widget>[
          Positioned(
            bottom: 6.0,
            right: 8.0,
            child: kDecoratedBoxA,
          ),
          Positioned(
            left: 10.0,
            right: 10.0,
            child: kDecoratedBoxB,
          ),
          kDecoratedBoxC,
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      TestParentData(bottom: 6.0, right: 8.0),
      TestParentData(left: 10.0, right: 10.0),
      kNonPositioned,
    ]);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          kDecoratedBoxA,
          Positioned(
            left: 11.0,
            right: 12.0,
            child: Container(child: kDecoratedBoxB),
          ),
          kDecoratedBoxC,
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      kNonPositioned,
      TestParentData(left: 11.0, right: 12.0),
      kNonPositioned,
    ]);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          kDecoratedBoxA,
          Positioned(
            right: 10.0,
            child: Container(child: kDecoratedBoxB),
          ),
          Container(
            child: const Positioned(
              top: 8.0,
              child: kDecoratedBoxC,
            ),
          ),
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      kNonPositioned,
      TestParentData(right: 10.0),
      TestParentData(top: 8.0),
    ]);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: const <Widget>[
          Positioned(
            right: 10.0,
            child: FlipWidget(left: kDecoratedBoxA, right: kDecoratedBoxB),
          ),
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      TestParentData(right: 10.0),
    ]);

    flipStatefulWidget(tester);
    await tester.pump();

    checkTree(tester, <TestParentData>[
      TestParentData(right: 10.0),
    ]);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: const <Widget>[
          Positioned(
            top: 7.0,
            child: FlipWidget(left: kDecoratedBoxA, right: kDecoratedBoxB),
          ),
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      TestParentData(top: 7.0),
    ]);

    flipStatefulWidget(tester);
    await tester.pump();

    checkTree(tester, <TestParentData>[
      TestParentData(top: 7.0),
    ]);

    await tester.pumpWidget(
      Stack(textDirection: TextDirection.ltr)
    );

    checkTree(tester, <TestParentData>[]);
  });

  testWidgets('ParentDataWidget conflicting data', (WidgetTester tester) async {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Stack(
          textDirection: TextDirection.ltr,
          children: const <Widget>[
            Positioned(
              top: 5.0,
              bottom: 8.0,
              child: Positioned(
                top: 6.0,
                left: 7.0,
                child: DecoratedBox(decoration: kBoxDecorationB),
              ),
            ),
          ],
        ),
      ),
    );

    dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Incorrect use of ParentDataWidget.\n'
        'The following ParentDataWidgets are providing parent data to the same RenderObject:\n'
        '- Positioned(left: 7.0, top: 6.0) (typically placed directly inside a Stack widget)\n'
        '- Positioned(top: 5.0, bottom: 8.0) (typically placed directly inside a Stack widget)\n'
        'However, a RenderObject can only receive parent data from at most one ParentDataWidget.\n'
        'Usually, this indicates that at least one of the offending ParentDataWidgets listed '
        'above is not placed directly inside a compatible ancestor widget.\n'
        'The ownership chain for the RenderObject that received the parent data was:\n'
        '  DecoratedBox ← Positioned ← Positioned ← Stack ← Directionality ← [root]'
      ),
    );

    await tester.pumpWidget(Stack(textDirection: TextDirection.ltr));

    checkTree(tester, <TestParentData>[]);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Container(
          child: Row(
            children: const <Widget>[
              Positioned(
                top: 6.0,
                left: 7.0,
                child: DecoratedBox(decoration: kBoxDecorationB),
              ),
            ],
          ),
        ),
      ),
    );
    exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Incorrect use of ParentDataWidget.\n'
        'The ParentDataWidget Positioned(left: 7.0, top: 6.0) wants to apply ParentData of type '
        'StackParentData to a RenderObject, which has been set up to accept ParentData of '
        'incompatible type FlexParentData.\n'
        'Usually, this means that the Positioned widget has the wrong ancestor RenderObjectWidget. '
        'Typically, Positioned widgets are placed directly inside Stack widgets.\n'
        'The offending Positioned is currently placed inside a Row widget.\n'
        'The ownership chain for the RenderObject that received the incompatible parent data was:\n'
        '  DecoratedBox ← Positioned ← Row ← Container ← Directionality ← [root]'
      ),
    );

    await tester.pumpWidget(
      Stack(textDirection: TextDirection.ltr)
    );

    checkTree(tester, <TestParentData>[]);
  });

  testWidgets('ParentDataWidget interacts with global keys', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          Positioned(
            top: 10.0,
            left: 10.0,
            child: DecoratedBox(key: key, decoration: kBoxDecorationA),
          ),
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      TestParentData(top: 10.0, left: 10.0),
    ]);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          Positioned(
            top: 10.0,
            left: 10.0,
            child: DecoratedBox(
              decoration: kBoxDecorationB,
              child: DecoratedBox(key: key, decoration: kBoxDecorationA),
            ),
          ),
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      TestParentData(top: 10.0, left: 10.0),
    ]);

    await tester.pumpWidget(
      Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          Positioned(
            top: 10.0,
            left: 10.0,
            child: DecoratedBox(key: key, decoration: kBoxDecorationA),
          ),
        ],
      ),
    );

    checkTree(tester, <TestParentData>[
      TestParentData(top: 10.0, left: 10.0),
    ]);
  });

  testWidgets('Parent data invalid ancestor', (WidgetTester tester) async {
    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: Row(
        children: <Widget>[
          Stack(
            textDirection: TextDirection.ltr,
            children: <Widget>[
              Expanded(
                child: Container(),
              ),
            ],
          ),
        ],
      ),
    ));

    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(
      exception.toString(),
      equalsIgnoringHashCodes(
        'Incorrect use of ParentDataWidget.\n'
        'The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type '
        'FlexParentData to a RenderObject, which has been set up to accept ParentData of '
        'incompatible type StackParentData.\n'
        'Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. '
        'Typically, Expanded widgets are placed directly inside Flex widgets.\n'
        'The offending Expanded is currently placed inside a Stack widget.\n'
        'The ownership chain for the RenderObject that received the incompatible parent data was:\n'
        '  LimitedBox ← Container ← Expanded ← Stack ← Row ← Directionality ← [root]'
      ),
    );
  });

  testWidgets('ParentDataWidget can be used with different ancestor RenderObjectWidgets', (WidgetTester tester) async {
    await tester.pumpWidget(
      OneAncestorWidget(
        child: Container(),
      ),
    );
    DummyParentData parentData = tester.renderObject(find.byType(Container)).parentData as DummyParentData;
    expect(parentData.string, isNull);

    await tester.pumpWidget(
      OneAncestorWidget(
        child: TestParentDataWidget(
          string: 'Foo',
          child: Container(),
        ),
      ),
    );
    parentData = tester.renderObject(find.byType(Container)).parentData as DummyParentData;
    expect(parentData.string, 'Foo');

    await tester.pumpWidget(
      AnotherAncestorWidget(
        child: TestParentDataWidget(
          string: 'Bar',
          child: Container(),
        ),
      ),
    );
    parentData = tester.renderObject(find.byType(Container)).parentData as DummyParentData;
    expect(parentData.string, 'Bar');
  });
}

class TestParentDataWidget extends ParentDataWidget<DummyParentData> {
  const TestParentDataWidget({
    Key key,
    this.string,
    Widget child,
  }) : super(key: key, child: child);

  final String string;

  @override
  void applyParentData(RenderObject renderObject) {
    assert(renderObject.parentData is DummyParentData);
    final DummyParentData parentData = renderObject.parentData as DummyParentData;
    parentData.string = string;
  }

  @override
  Type get debugTypicalAncestorWidgetClass => OneAncestorWidget;
}

class DummyParentData extends ParentData {
  String string;
}

class OneAncestorWidget extends SingleChildRenderObjectWidget {
  const OneAncestorWidget({
    Key key,
    Widget child,
  }) : super(key: key, child: child);

  @override
  RenderOne createRenderObject(BuildContext context) => RenderOne();
}

class AnotherAncestorWidget extends SingleChildRenderObjectWidget {
  const AnotherAncestorWidget({
    Key key,
    Widget child,
  }) : super(key: key, child: child);

  @override
  RenderAnother createRenderObject(BuildContext context) => RenderAnother();
}

class RenderOne extends RenderProxyBox {
  @override
  void setupParentData(RenderBox child) {
    if (child.parentData is! DummyParentData)
      child.parentData = DummyParentData();
  }
}

class RenderAnother extends RenderProxyBox {
  @override
  void setupParentData(RenderBox child) {
    if (child.parentData is! DummyParentData)
      child.parentData = DummyParentData();
  }
}
