// 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 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';

import 'rendering_tester.dart';

void main() {
  TestRenderingFlutterBinding.ensureInitialized();

  test('PipelineOwner dispatches memory events', () async {
    await expectLater(
      await memoryEvents(() => PipelineOwner().dispose(), PipelineOwner),
      areCreateAndDispose,
    );
  });

  test('nodesNeedingLayout updated with layout changes', () {
    final owner = _TestPipelineOwner();
    final renderObject = TestRenderObject()..isRepaintBoundary = true;
    renderObject.attach(owner);
    expect(owner.needLayout, isEmpty);

    renderObject.layout(const BoxConstraints.tightForFinite());
    renderObject.markNeedsLayout();
    expect(owner.needLayout, contains(renderObject));

    owner.flushLayout();
    expect(owner.needLayout, isEmpty);
  });

  test('nodesNeedingPaint updated with paint changes', () {
    final owner = _TestPipelineOwner();
    final renderObject = TestRenderObject(allowPaintBounds: true)..isRepaintBoundary = true;
    final layer = OffsetLayer();
    layer.attach(owner);
    renderObject.attach(owner);
    expect(owner.needPaint, isEmpty);

    renderObject.markNeedsPaint();
    renderObject.scheduleInitialPaint(layer);
    expect(owner.needPaint, contains(renderObject));

    owner.flushPaint();
    expect(owner.needPaint, isEmpty);
  });

  test('ensure frame is scheduled for markNeedsSemanticsUpdate', () {
    // Initialize all bindings because owner.flushSemantics() requires a window
    final renderObject = TestRenderObject();
    var onNeedVisualUpdateCallCount = 0;
    final owner = PipelineOwner(
      onNeedVisualUpdate: () {
        onNeedVisualUpdateCallCount += 1;
      },
      onSemanticsUpdate: (ui.SemanticsUpdate update) {},
    );
    owner.ensureSemantics();
    owner.rootNode = renderObject;
    renderObject.layout(
      const BoxConstraints.tightForFinite(),
    ); // semantics are only calculated if layout information is up to date.
    owner.flushSemantics();

    expect(onNeedVisualUpdateCallCount, 1);
    renderObject.markNeedsSemanticsUpdate();
    expect(onNeedVisualUpdateCallCount, 2);
  });

  test('onSemanticsUpdate is called during flushSemantics.', () {
    var onSemanticsUpdateCallCount = 0;
    final owner = PipelineOwner(
      onSemanticsUpdate: (ui.SemanticsUpdate update) {
        onSemanticsUpdateCallCount += 1;
      },
    );
    owner.ensureSemantics();

    expect(onSemanticsUpdateCallCount, 0);

    final renderObject = TestRenderObject();
    owner.rootNode = renderObject;
    renderObject.layout(const BoxConstraints.tightForFinite());
    owner.flushSemantics();

    expect(onSemanticsUpdateCallCount, 1);
  });

  test('Enabling semantics without configuring onSemanticsUpdate is invalid.', () {
    final pipelineOwner = PipelineOwner();
    expect(() => pipelineOwner.ensureSemantics(), throwsAssertionError);
  });

  test('onSemanticsUpdate during sendSemanticsUpdate.', () {
    var onSemanticsUpdateCallCount = 0;
    final owner = SemanticsOwner(
      onSemanticsUpdate: (ui.SemanticsUpdate update) {
        onSemanticsUpdateCallCount += 1;
      },
    );

    final node = SemanticsNode.root(owner: owner);
    node.rect = Rect.largest;

    expect(onSemanticsUpdateCallCount, 0);

    owner.sendSemanticsUpdate();

    expect(onSemanticsUpdateCallCount, 1);
  });

  test('detached RenderObject does not do semantics', () {
    final renderObject = TestRenderObject();
    expect(renderObject.attached, isFalse);
    expect(renderObject.describeSemanticsConfigurationCallCount, 0);

    renderObject.markNeedsSemanticsUpdate();
    expect(renderObject.describeSemanticsConfigurationCallCount, 0);
  });

  test('ensure errors processing render objects are well formatted', () {
    late FlutterErrorDetails errorDetails;
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = (FlutterErrorDetails details) {
      errorDetails = details;
    };
    final owner = PipelineOwner();
    final renderObject = TestThrowingRenderObject();
    try {
      renderObject.attach(owner);
      renderObject.layout(const BoxConstraints());
    } finally {
      FlutterError.onError = oldHandler;
    }

    expect(errorDetails, isNotNull);
    expect(errorDetails.stack, isNotNull);
    // Check the ErrorDetails without the stack trace
    final List<String> lines = errorDetails.toString().split('\n');
    // The lines in the middle of the error message contain the stack trace
    // which will change depending on where the test is run.
    expect(lines.length, greaterThan(8));
    expect(
      lines.take(4).join('\n'),
      equalsIgnoringHashCodes(
        '══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞══════════════════════\n'
        'The following assertion was thrown during performLayout():\n'
        'TestThrowingRenderObject does not support performLayout.\n',
      ),
    );

    expect(
      lines.getRange(lines.length - 8, lines.length).join('\n'),
      equalsIgnoringHashCodes(
        '\n'
        'The following RenderObject was being processed when the exception was fired:\n'
        '  TestThrowingRenderObject#00000 NEEDS-PAINT:\n'
        '  parentData: MISSING\n'
        '  constraints: BoxConstraints(unconstrained)\n'
        'This RenderObject has no descendants.\n'
        '═════════════════════════════════════════════════════════════════\n',
      ),
    );
  });

  test('ContainerParentDataMixin requires nulled out pointers to siblings before detach', () {
    expect(() => TestParentData().detach(), isNot(throwsAssertionError));

    final data1 = TestParentData()
      ..nextSibling = RenderOpacity()
      ..previousSibling = RenderOpacity();
    expect(() => data1.detach(), throwsAssertionError);

    final data2 = TestParentData()..previousSibling = RenderOpacity();
    expect(() => data2.detach(), throwsAssertionError);

    final data3 = TestParentData()..nextSibling = RenderOpacity();
    expect(() => data3.detach(), throwsAssertionError);
  });

  test('RenderObject.getTransformTo asserts if target not in the same render tree', () {
    final owner = PipelineOwner();
    final renderObject1 = TestRenderObject();
    renderObject1.attach(owner);
    final renderObject2 = TestRenderObject();
    renderObject2.attach(owner);
    expect(() => renderObject1.getTransformTo(renderObject2), throwsAssertionError);
  });

  test('RenderObject.getTransformTo works for siblings and descendants', () {
    final owner = PipelineOwner();
    final renderObject1 = TestRenderObject()..attach(owner);
    final renderObject11 = TestRenderObject();
    final renderObject12 = TestRenderObject();

    renderObject1
      ..add(renderObject11)
      ..add(renderObject12);
    expect(renderObject11.getTransformTo(renderObject12), equals(Matrix4.identity()));
    expect(renderObject1.getTransformTo(renderObject11), equals(Matrix4.identity()));
    expect(renderObject1.getTransformTo(renderObject12), equals(Matrix4.identity()));
    expect(renderObject11.getTransformTo(renderObject1), equals(Matrix4.identity()));
    expect(renderObject12.getTransformTo(renderObject1), equals(Matrix4.identity()));

    expect(renderObject1.getTransformTo(renderObject1), equals(Matrix4.identity()));
    expect(renderObject11.getTransformTo(renderObject11), equals(Matrix4.identity()));
    expect(renderObject12.getTransformTo(renderObject12), equals(Matrix4.identity()));
  });

  test('RenderObject.getTransformTo gets the correct paint transform', () {
    final owner = PipelineOwner();
    final renderObject0 = TestRenderObject()..attach(owner);
    final renderObject1 = TestRenderObject();
    final renderObject2 = TestRenderObject();
    renderObject0
      ..add(renderObject1)
      ..add(renderObject2)
      ..paintTransform = Matrix4.diagonal3Values(9, 4, 1);

    final renderObject11 = TestRenderObject();
    final renderObject21 = TestRenderObject();
    renderObject1
      ..add(renderObject11)
      ..paintTransform = Matrix4.translationValues(8, 16, 32);
    renderObject2
      ..add(renderObject21)
      ..paintTransform = Matrix4.translationValues(32, 64, 128);

    expect(
      renderObject11.getTransformTo(renderObject21),
      equals(Matrix4.translationValues((8 - 32) * 9, (16 - 64) * 4, 32 - 128)),
    );
    // Turn one of the paint transforms into a singular matrix and getTransformTo
    // should return Matrix4.zero().
    renderObject0.paintTransform = Matrix4(
      1,
      1,
      1,
      1,
      2,
      2,
      2,
      2,
      3,
      3,
      3,
      3,
      4,
      4,
      4,
      4,
    ); // Not a full rank matrix, so it has to be singular.
    expect(renderObject11.getTransformTo(renderObject21), equals(Matrix4.zero()));
  });

  test('PaintingContext.pushClipRect reuses the layer', () {
    _testPaintingContextLayerReuse<ClipRectLayer>((
      PaintingContextCallback painter,
      PaintingContext context,
      Offset offset,
      Layer? oldLayer,
    ) {
      return context.pushClipRect(
        true,
        offset,
        Rect.zero,
        painter,
        oldLayer: oldLayer as ClipRectLayer?,
      );
    });
  });

  test('PaintingContext.pushClipRRect reuses the layer', () {
    _testPaintingContextLayerReuse<ClipRRectLayer>((
      PaintingContextCallback painter,
      PaintingContext context,
      Offset offset,
      Layer? oldLayer,
    ) {
      return context.pushClipRRect(
        true,
        offset,
        Rect.zero,
        RRect.fromRectAndRadius(Rect.zero, const Radius.circular(1.0)),
        painter,
        oldLayer: oldLayer as ClipRRectLayer?,
      );
    });
  });

  test('PaintingContext.pushClipRSuperellipse reuses the layer', () {
    _testPaintingContextLayerReuse<ClipRSuperellipseLayer>((
      PaintingContextCallback painter,
      PaintingContext context,
      Offset offset,
      Layer? oldLayer,
    ) {
      return context.pushClipRSuperellipse(
        true,
        offset,
        Rect.zero,
        RSuperellipse.fromRectAndRadius(Rect.zero, const Radius.circular(1.0)),
        painter,
        oldLayer: oldLayer as ClipRSuperellipseLayer?,
      );
    });
  });

  test('PaintingContext.pushClipPath reuses the layer', () {
    _testPaintingContextLayerReuse<ClipPathLayer>((
      PaintingContextCallback painter,
      PaintingContext context,
      Offset offset,
      Layer? oldLayer,
    ) {
      return context.pushClipPath(
        true,
        offset,
        Rect.zero,
        Path(),
        painter,
        oldLayer: oldLayer as ClipPathLayer?,
      );
    });
  });

  test('PaintingContext.pushColorFilter reuses the layer', () {
    _testPaintingContextLayerReuse<ColorFilterLayer>((
      PaintingContextCallback painter,
      PaintingContext context,
      Offset offset,
      Layer? oldLayer,
    ) {
      return context.pushColorFilter(
        offset,
        const ColorFilter.mode(Color.fromRGBO(0, 0, 0, 1.0), BlendMode.clear),
        painter,
        oldLayer: oldLayer as ColorFilterLayer?,
      );
    });
  });

  test('PaintingContext.pushTransform reuses the layer', () {
    _testPaintingContextLayerReuse<TransformLayer>((
      PaintingContextCallback painter,
      PaintingContext context,
      Offset offset,
      Layer? oldLayer,
    ) {
      return context.pushTransform(
        true,
        offset,
        Matrix4.identity(),
        painter,
        oldLayer: oldLayer as TransformLayer?,
      );
    });
  });

  test('PaintingContext.pushOpacity reuses the layer', () {
    _testPaintingContextLayerReuse<OpacityLayer>((
      PaintingContextCallback painter,
      PaintingContext context,
      Offset offset,
      Layer? oldLayer,
    ) {
      return context.pushOpacity(offset, 100, painter, oldLayer: oldLayer as OpacityLayer?);
    });
  });

  test('RenderObject.dispose sets debugDisposed to true', () {
    final renderObject = TestRenderObject();
    expect(renderObject.debugDisposed, false);
    renderObject.dispose();
    expect(renderObject.debugDisposed, true);
    expect(renderObject.toStringShort(), contains('DISPOSED'));
  });

  test('Leader layer can switch to a different render object within one frame', () {
    List<FlutterErrorDetails?>? caughtErrors;
    TestRenderingFlutterBinding.instance.onErrors = () {
      caughtErrors = TestRenderingFlutterBinding.instance.takeAllFlutterErrorDetails().toList();
    };

    final layerLink = LayerLink();
    // renderObject1 paints the leader layer first.
    final renderObject1 = LeaderLayerRenderObject();
    renderObject1.layerLink = layerLink;
    renderObject1.attach(TestRenderingFlutterBinding.instance.pipelineOwner);
    final rootLayer1 = OffsetLayer();
    rootLayer1.attach(renderObject1);
    renderObject1.scheduleInitialPaint(rootLayer1);
    renderObject1.layout(const BoxConstraints.tightForFinite());

    final renderObject2 = LeaderLayerRenderObject();
    final rootLayer2 = OffsetLayer();
    rootLayer2.attach(renderObject2);
    renderObject2.attach(TestRenderingFlutterBinding.instance.pipelineOwner);
    renderObject2.scheduleInitialPaint(rootLayer2);
    renderObject2.layout(const BoxConstraints.tightForFinite());
    TestRenderingFlutterBinding.instance.pumpCompleteFrame();

    // Swap the layer link to renderObject2 in the same frame
    renderObject1.layerLink = null;
    renderObject1.markNeedsPaint();
    renderObject2.layerLink = layerLink;
    renderObject2.markNeedsPaint();
    TestRenderingFlutterBinding.instance.pumpCompleteFrame();

    // Swap the layer link to renderObject1 in the same frame
    renderObject1.layerLink = layerLink;
    renderObject1.markNeedsPaint();
    renderObject2.layerLink = null;
    renderObject2.markNeedsPaint();
    TestRenderingFlutterBinding.instance.pumpCompleteFrame();

    TestRenderingFlutterBinding.instance.onErrors = null;
    expect(caughtErrors, isNull);
  });

  test('Leader layer append to two render objects does crash', () {
    List<FlutterErrorDetails?>? caughtErrors;
    TestRenderingFlutterBinding.instance.onErrors = () {
      caughtErrors = TestRenderingFlutterBinding.instance.takeAllFlutterErrorDetails().toList();
    };
    final layerLink = LayerLink();
    // renderObject1 paints the leader layer first.
    final renderObject1 = LeaderLayerRenderObject();
    renderObject1.layerLink = layerLink;
    renderObject1.attach(TestRenderingFlutterBinding.instance.pipelineOwner);
    final rootLayer1 = OffsetLayer();
    rootLayer1.attach(renderObject1);
    renderObject1.scheduleInitialPaint(rootLayer1);
    renderObject1.layout(const BoxConstraints.tightForFinite());

    final renderObject2 = LeaderLayerRenderObject();
    renderObject2.layerLink = layerLink;
    final rootLayer2 = OffsetLayer();
    rootLayer2.attach(renderObject2);
    renderObject2.attach(TestRenderingFlutterBinding.instance.pipelineOwner);
    renderObject2.scheduleInitialPaint(rootLayer2);
    renderObject2.layout(const BoxConstraints.tightForFinite());
    TestRenderingFlutterBinding.instance.pumpCompleteFrame();

    TestRenderingFlutterBinding.instance.onErrors = null;
    expect(caughtErrors!.isNotEmpty, isTrue);
  });

  test('RenderObject.dispose null the layer on repaint boundaries', () {
    final renderObject = TestRenderObject(allowPaintBounds: true);
    // Force a layer to get set.
    renderObject.isRepaintBoundary = true;
    PaintingContext.repaintCompositedChild(renderObject, debugAlsoPaintedParent: true);
    expect(renderObject.debugLayer, isA<OffsetLayer>());

    // Dispose with repaint boundary still being true.
    renderObject.dispose();
    expect(renderObject.debugLayer, null);
  });

  test('RenderObject.dispose nulls the layer on non-repaint boundaries', () {
    final renderObject = TestRenderObject(allowPaintBounds: true);
    // Force a layer to get set.
    renderObject.isRepaintBoundary = true;
    PaintingContext.repaintCompositedChild(renderObject, debugAlsoPaintedParent: true);

    // Dispose with repaint boundary being false.
    renderObject.isRepaintBoundary = false;
    renderObject.dispose();
    expect(renderObject.debugLayer, null);
  });

  test('Add composition callback works', () {
    final root = ContainerLayer();
    final context = PaintingContext(root, Rect.zero);
    var calledBack = false;
    final object = TestObservingRenderObject((Layer layer) {
      expect(layer, root);
      calledBack = true;
    });

    expect(calledBack, false);
    object.paint(context, Offset.zero);
    expect(calledBack, false);

    root.buildScene(ui.SceneBuilder()).dispose();
    expect(calledBack, true);
  });

  test('Change isRepaintBoundary after both markNeedsCompositedLayerUpdate and markNeedsPaint', () {
    List<FlutterErrorDetails?>? caughtErrors;
    TestRenderingFlutterBinding.instance.onErrors = () {
      caughtErrors = TestRenderingFlutterBinding.instance.takeAllFlutterErrorDetails().toList();
    };
    final object = TestRenderObject(allowPaintBounds: true);
    object.isRepaintBoundary = true;
    object.attach(TestRenderingFlutterBinding.instance.pipelineOwner);
    object.layout(const BoxConstraints.tightForFinite());
    PaintingContext.repaintCompositedChild(object, debugAlsoPaintedParent: true);

    object.markNeedsCompositedLayerUpdate();
    object.markNeedsPaint();
    object.isRepaintBoundary = false;
    object.markNeedsCompositingBitsUpdate();
    TestRenderingFlutterBinding.instance.pumpCompleteFrame();
    expect(caughtErrors, isNull);
  });

  test('ContainerParentDataMixin asserts parentData type', () {
    final TestRenderObject renderObject = TestRenderObjectWithoutSetupParentData();
    final child = TestRenderObject();
    expect(
      () => renderObject.add(child),
      throwsA(
        isA<AssertionError>().having(
          (AssertionError error) => error.toString(),
          'description',
          contains(
            'A child of TestRenderObjectWithoutSetupParentData has parentData of type ParentData, '
            'which does not conform to TestRenderObjectParentData. Class using ContainerRenderObjectMixin '
            'should override setupParentData() to set parentData to type TestRenderObjectParentData.',
          ),
        ),
      ),
    );
  });

  test('PictureRecorder getter', () {
    final context = PaintingContext(ContainerLayer(), Rect.zero);
    expect(context.recorder.isRecording, isTrue);
  });
}

class TestObservingRenderObject extends RenderBox {
  TestObservingRenderObject(this.callback);

  final CompositionCallback callback;

  @override
  bool get sizedByParent => true;

  @override
  void paint(PaintingContext context, Offset offset) {
    context.addCompositionCallback(callback);
  }
}

// Tests the create-update cycle by pumping two frames. The first frame has no
// prior layer and forces the painting context to create a new one. The second
// frame reuses the layer painted on the first frame.
void _testPaintingContextLayerReuse<L extends Layer>(_LayerTestPaintCallback painter) {
  final box = _TestCustomLayerBox(painter);
  layout(box, phase: EnginePhase.paint);

  // Force a repaint. Otherwise, pumpFrame is a noop.
  box.markNeedsPaint();
  pumpFrame(phase: EnginePhase.paint);
  expect(box.paintedLayers, hasLength(2));
  expect(box.paintedLayers[0], isA<L>());
  expect(box.paintedLayers[0], same(box.paintedLayers[1]));
}

typedef _LayerTestPaintCallback =
    Layer? Function(
      PaintingContextCallback painter,
      PaintingContext context,
      Offset offset,
      Layer? oldLayer,
    );

class _TestCustomLayerBox extends RenderBox {
  _TestCustomLayerBox(this.painter);

  final _LayerTestPaintCallback painter;
  final List<Layer> paintedLayers = <Layer>[];

  @override
  bool get isRepaintBoundary => false;

  @override
  void performLayout() {
    size = constraints.smallest;
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    final Layer paintedLayer = painter(super.paint, context, offset, layer)!;
    paintedLayers.add(paintedLayer);
    layer = paintedLayer as ContainerLayer;
  }
}

class TestParentData extends ParentData with ContainerParentDataMixin<RenderBox> {}

class TestRenderObjectParentData extends ParentData
    with ContainerParentDataMixin<TestRenderObject> {}

class TestRenderObject extends RenderObject
    with ContainerRenderObjectMixin<TestRenderObject, TestRenderObjectParentData> {
  TestRenderObject({this.allowPaintBounds = false});

  final bool allowPaintBounds;

  @override
  bool isRepaintBoundary = false;

  @override
  void debugAssertDoesMeetConstraints() {}

  @override
  Rect get paintBounds {
    assert(allowPaintBounds); // For some tests, this should not get called.
    return Rect.zero;
  }

  Matrix4 paintTransform = Matrix4.identity();
  @override
  void applyPaintTransform(covariant RenderObject child, Matrix4 transform) {
    super.applyPaintTransform(child, transform);
    transform.multiply(paintTransform);
  }

  @override
  void setupParentData(RenderObject child) {
    if (child.parentData is! TestRenderObjectParentData) {
      child.parentData = TestRenderObjectParentData();
    }
  }

  @override
  void performLayout() {}

  @override
  void performResize() {}

  @override
  Rect get semanticBounds => const Rect.fromLTWH(0.0, 0.0, 10.0, 20.0);

  int describeSemanticsConfigurationCallCount = 0;

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    config.isSemanticBoundary = true;
    describeSemanticsConfigurationCallCount++;
  }
}

class TestRenderObjectWithoutSetupParentData extends TestRenderObject {
  @override
  void setupParentData(RenderObject child) {
    // Use a mismatched parent data type.
    if (child.parentData is! ParentData) {
      child.parentData = ParentData();
    }
  }
}

class LeaderLayerRenderObject extends RenderObject {
  LeaderLayerRenderObject();

  LayerLink? layerLink;

  @override
  bool isRepaintBoundary = true;

  @override
  void debugAssertDoesMeetConstraints() {}

  @override
  Rect get paintBounds {
    return Rect.zero;
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    if (layerLink != null) {
      context.pushLayer(LeaderLayer(link: layerLink!), super.paint, offset);
    }
  }

  @override
  void performLayout() {}

  @override
  void performResize() {}

  @override
  Rect get semanticBounds => const Rect.fromLTWH(0.0, 0.0, 10.0, 20.0);
}

class TestThrowingRenderObject extends RenderObject {
  @override
  void performLayout() {
    throw FlutterError('TestThrowingRenderObject does not support performLayout.');
  }

  @override
  void debugAssertDoesMeetConstraints() {}

  @override
  Rect get paintBounds {
    assert(false); // The test shouldn't call this.
    return Rect.zero;
  }

  @override
  void performResize() {}

  @override
  Rect get semanticBounds {
    assert(false); // The test shouldn't call this.
    return Rect.zero;
  }
}

final class _TestPipelineOwner extends PipelineOwner {
  // Make these protected fields visible for testing.
  Iterable<RenderObject> get needLayout => super.nodesNeedingLayout;

  Iterable<RenderObject> get needPaint => super.nodesNeedingPaint;
}
