// 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_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();
  }
}
