// 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 '../rendering/recording_canvas.dart';

final BoxDecoration kBoxDecorationA = BoxDecoration(border: nonconst(null));
final BoxDecoration kBoxDecorationB = BoxDecoration(border: nonconst(null));
final BoxDecoration kBoxDecorationC = BoxDecoration(border: nonconst(null));

class TestWidget extends StatelessWidget {
  const TestWidget({
    Key? key,
    required this.child,
  }) : super(key: key);

  final Widget child;

  @override
  Widget build(BuildContext context) => child;
}

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

  Decoration _getDecoration(BuildContext context) {
    final Orientation orientation = MediaQuery.of(context).orientation;
    switch (orientation) {
      case Orientation.landscape:
        return const BoxDecoration(color: Color(0xFF00FF00));
      case Orientation.portrait:
        return const BoxDecoration(color: Color(0xFF0000FF));
    }
  }

  @override
  RenderDecoratedBox createRenderObject(BuildContext context) => RenderDecoratedBox(decoration: _getDecoration(context));

  @override
  void updateRenderObject(BuildContext context, RenderDecoratedBox renderObject) {
    renderObject.decoration = _getDecoration(context);
  }
}

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

  @override
  RenderObject createRenderObject(BuildContext context) => TestNonVisitingRenderObject();
}

class TestNonVisitingRenderObject extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
  @override
  Size computeDryLayout(BoxConstraints constraints) {
    return child!.getDryLayout(constraints);
  }

  @override
  void performLayout() {
    child!.layout(constraints, parentUsesSize: true);
    size = child!.size;
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    context.paintChild(child!, offset);
  }

  @override
  void visitChildren(RenderObjectVisitor visitor) {
    // oops!
  }
}

void main() {
  testWidgets('RenderObjectWidget smoke test', (WidgetTester tester) async {
    await tester.pumpWidget(DecoratedBox(decoration: kBoxDecorationA));
    SingleChildRenderObjectElement element =
        tester.element(find.byElementType(SingleChildRenderObjectElement));
    expect(element, isNotNull);
    expect(element.renderObject, isA<RenderDecoratedBox>());
    RenderDecoratedBox renderObject = element.renderObject as RenderDecoratedBox;
    expect(renderObject.decoration, equals(kBoxDecorationA));
    expect(renderObject.position, equals(DecorationPosition.background));

    await tester.pumpWidget(DecoratedBox(decoration: kBoxDecorationB));
    element = tester.element(find.byElementType(SingleChildRenderObjectElement));
    expect(element, isNotNull);
    expect(element.renderObject, isA<RenderDecoratedBox>());
    renderObject = element.renderObject as RenderDecoratedBox;
    expect(renderObject.decoration, equals(kBoxDecorationB));
    expect(renderObject.position, equals(DecorationPosition.background));
  });

  testWidgets('RenderObjectWidget can add and remove children', (WidgetTester tester) async {

    void checkFullTree() {
      final SingleChildRenderObjectElement element =
          tester.firstElement(find.byElementType(SingleChildRenderObjectElement));
      expect(element, isNotNull);
      expect(element.renderObject, isA<RenderDecoratedBox>());
      final RenderDecoratedBox renderObject = element.renderObject as RenderDecoratedBox;
      expect(renderObject.decoration, equals(kBoxDecorationA));
      expect(renderObject.position, equals(DecorationPosition.background));
      expect(renderObject.child, isNotNull);
      expect(renderObject.child, isA<RenderDecoratedBox>());
      final RenderDecoratedBox child = renderObject.child! as RenderDecoratedBox;
      expect(child.decoration, equals(kBoxDecorationB));
      expect(child.position, equals(DecorationPosition.background));
      expect(child.child, isNull);
    }

    void childBareTree() {
      final SingleChildRenderObjectElement element =
          tester.element(find.byElementType(SingleChildRenderObjectElement));
      expect(element, isNotNull);
      expect(element.renderObject, isA<RenderDecoratedBox>());
      final RenderDecoratedBox renderObject = element.renderObject as RenderDecoratedBox;
      expect(renderObject.decoration, equals(kBoxDecorationA));
      expect(renderObject.position, equals(DecorationPosition.background));
      expect(renderObject.child, isNull);
    }

    await tester.pumpWidget(DecoratedBox(
      decoration: kBoxDecorationA,
      child: DecoratedBox(
        decoration: kBoxDecorationB
      ),
    ));

    checkFullTree();

    await tester.pumpWidget(DecoratedBox(
      decoration: kBoxDecorationA,
      child: TestWidget(
        child: DecoratedBox(
          decoration: kBoxDecorationB
        ),
      ),
    ));

    checkFullTree();

    await tester.pumpWidget(DecoratedBox(
      decoration: kBoxDecorationA,
      child: DecoratedBox(
        decoration: kBoxDecorationB
      ),
    ));

    checkFullTree();

    await tester.pumpWidget(DecoratedBox(
      decoration: kBoxDecorationA
    ));

    childBareTree();

    await tester.pumpWidget(DecoratedBox(
      decoration: kBoxDecorationA,
      child: TestWidget(
        child: TestWidget(
          child: DecoratedBox(
            decoration: kBoxDecorationB
          ),
        ),
      ),
    ));

    checkFullTree();

    await tester.pumpWidget(DecoratedBox(
      decoration: kBoxDecorationA
    ));

    childBareTree();
  });

  testWidgets('Detached render tree is intact', (WidgetTester tester) async {

    await tester.pumpWidget(DecoratedBox(
      decoration: kBoxDecorationA,
      child: DecoratedBox(
        decoration: kBoxDecorationB,
        child: DecoratedBox(
          decoration: kBoxDecorationC
        ),
      ),
    ));

    SingleChildRenderObjectElement element =
        tester.firstElement(find.byElementType(SingleChildRenderObjectElement));
    expect(element.renderObject, isA<RenderDecoratedBox>());
    final RenderDecoratedBox parent = element.renderObject as RenderDecoratedBox;
    expect(parent.child, isA<RenderDecoratedBox>());
    final RenderDecoratedBox child = parent.child! as RenderDecoratedBox;
    expect(child.decoration, equals(kBoxDecorationB));
    expect(child.child, isA<RenderDecoratedBox>());
    final RenderDecoratedBox grandChild = child.child! as RenderDecoratedBox;
    expect(grandChild.decoration, equals(kBoxDecorationC));
    expect(grandChild.child, isNull);

    await tester.pumpWidget(DecoratedBox(
      decoration: kBoxDecorationA
    ));

    element =
        tester.element(find.byElementType(SingleChildRenderObjectElement));
    expect(element.renderObject, isA<RenderDecoratedBox>());
    expect(element.renderObject, equals(parent));
    expect(parent.child, isNull);

    expect(child.parent, isNull);
    expect(child.decoration, equals(kBoxDecorationB));
    expect(child.child, equals(grandChild));
    expect(grandChild.parent, equals(child));
    expect(grandChild.decoration, equals(kBoxDecorationC));
    expect(grandChild.child, isNull);
  });

  testWidgets('Can watch inherited widgets', (WidgetTester tester) async {
    final Key boxKey = UniqueKey();
    final TestOrientedBox box = TestOrientedBox(key: boxKey);

    await tester.pumpWidget(MediaQuery(
      data: const MediaQueryData(size: Size(400.0, 300.0)),
      child: box,
    ));

    final RenderDecoratedBox renderBox = tester.renderObject(find.byKey(boxKey));
    BoxDecoration decoration = renderBox.decoration as BoxDecoration;
    expect(decoration.color, equals(const Color(0xFF00FF00)));

    await tester.pumpWidget(MediaQuery(
      data: const MediaQueryData(size: Size(300.0, 400.0)),
      child: box,
    ));

    decoration = renderBox.decoration as BoxDecoration;
    expect(decoration.color, equals(const Color(0xFF0000FF)));
  });

  testWidgets('RenderObject not visiting children provides helpful error message', (WidgetTester tester) async {
    await tester.pumpWidget(
      TestNonVisitingWidget(
        child: Container(color: const Color(0xFFED1D7F)),
      ),
    );

    final RenderObject renderObject = tester.renderObject(find.byType(TestNonVisitingWidget));
    final Canvas testCanvas = TestRecordingCanvas();
    final PaintingContext testContext = TestRecordingPaintingContext(testCanvas);

    // When a parent fails to visit a child in visitChildren, the child's compositing
    // bits won't be cleared properly, leading to an exception during paint.
    renderObject.paint(testContext, Offset.zero);

    final dynamic error = tester.takeException();
    expect(error, isNotNull, reason: 'RenderObject did not throw when painting');
    expect(error, isFlutterError);
    expect(error.toString(), contains("A RenderObject was not visited by the parent's visitChildren"));
  });
}
