// 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/material.dart';
import 'package:flutter/rendering.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('ensure frame is scheduled for markNeedsSemanticsUpdate', () {
    // Initialize all bindings because owner.flushSemantics() requires a window
    final TestRenderObject renderObject = TestRenderObject();
    int onNeedVisualUpdateCallCount = 0;
    final PipelineOwner owner = PipelineOwner(
      onNeedVisualUpdate: () {
        onNeedVisualUpdateCallCount +=1;
      },
      onSemanticsUpdate: (ui.SemanticsUpdate update) {}
    );
    owner.ensureSemantics();
    renderObject.attach(owner);
    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.', () {
    int onSemanticsUpdateCallCount = 0;
    final PipelineOwner owner = PipelineOwner(
      onSemanticsUpdate: (ui.SemanticsUpdate update) {
        onSemanticsUpdateCallCount += 1;
      },
    );
    owner.ensureSemantics();

    expect(onSemanticsUpdateCallCount, 0);

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

    expect(onSemanticsUpdateCallCount, 1);
  });

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


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

    final SemanticsNode 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 TestRenderObject 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 PipelineOwner owner = PipelineOwner();
    final TestThrowingRenderObject 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 TestParentData data1 = TestParentData()
      ..nextSibling = RenderOpacity()
      ..previousSibling = RenderOpacity();
    expect(() => data1.detach(), throwsAssertionError);

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

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

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

  test('RenderObject.getTransformTo works for siblings and descendants', () {
    final PipelineOwner owner = PipelineOwner();
    final TestRenderObject renderObject1 = TestRenderObject()..attach(owner);
    final TestRenderObject renderObject11 = TestRenderObject();
    final TestRenderObject 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 PipelineOwner owner = PipelineOwner();
    final TestRenderObject renderObject0 = TestRenderObject()
      ..attach(owner);
    final TestRenderObject renderObject1 = TestRenderObject();
    final TestRenderObject renderObject2 = TestRenderObject();
    renderObject0
      ..add(renderObject1)
      ..add(renderObject2)
      ..paintTransform = Matrix4.diagonal3Values(9, 4, 1);

    final TestRenderObject renderObject11 = TestRenderObject();
    final TestRenderObject 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.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 TestRenderObject 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 = LayerLink();
    // renderObject1 paints the leader layer first.
    final LeaderLayerRenderObject renderObject1 = LeaderLayerRenderObject();
    renderObject1.layerLink = layerLink;
    renderObject1.attach(TestRenderingFlutterBinding.instance.pipelineOwner);
    final OffsetLayer rootLayer1 = OffsetLayer();
    rootLayer1.attach(renderObject1);
    renderObject1.scheduleInitialPaint(rootLayer1);
    renderObject1.layout(const BoxConstraints.tightForFinite());

    final LeaderLayerRenderObject renderObject2 = LeaderLayerRenderObject();
    final OffsetLayer 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 = LayerLink();
    // renderObject1 paints the leader layer first.
    final LeaderLayerRenderObject renderObject1 = LeaderLayerRenderObject();
    renderObject1.layerLink = layerLink;
    renderObject1.attach(TestRenderingFlutterBinding.instance.pipelineOwner);
    final OffsetLayer rootLayer1 = OffsetLayer();
    rootLayer1.attach(renderObject1);
    renderObject1.scheduleInitialPaint(rootLayer1);
    renderObject1.layout(const BoxConstraints.tightForFinite());

    final LeaderLayerRenderObject renderObject2 = LeaderLayerRenderObject();
    renderObject2.layerLink = layerLink;
    final OffsetLayer 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 TestRenderObject 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 TestRenderObject 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 ContainerLayer root = ContainerLayer();
    final PaintingContext context = PaintingContext(root, Rect.zero);
    bool calledBack = false;
    final TestObservingRenderObject 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);
  });
}


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 _TestCustomLayerBox 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 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;
  }
}
