// 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/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';

import 'rendering_tester.dart';

void main() {
  // This test has to be kept separate from object_test.dart because the way
  // the rendering_test.dart dependency of this test uses the bindings in not
  // compatible with existing tests in object_test.dart.
  test('reentrant paint error', () {
    late FlutterErrorDetails errorDetails;
    final RenderBox root = TestReentrantPaintingErrorRenderBox();
    layout(root, onErrors: () {
      errorDetails = renderer.takeFlutterErrorDetails()!;
    });
    pumpFrame(phase: EnginePhase.paint);

    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(12));
    expect(
      lines.take(12).join('\n'),
      equalsIgnoringHashCodes(
        '══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞══════════════════════\n'
        'The following assertion was thrown during paint():\n'
        'Tried to paint a RenderObject reentrantly.\n'
        'The following RenderObject was already being painted when it was painted again:\n'
        '  TestReentrantPaintingErrorRenderBox#00000:\n'
        '  parentData: <none>\n'
        '  constraints: BoxConstraints(w=800.0, h=600.0)\n'
        '  size: Size(100.0, 100.0)\n'
        'Since this typically indicates an infinite recursion, it is\n'
        'disallowed.\n'
        '\n'
        'When the exception was thrown, this was the stack:',
      ),
    );

    expect(
      lines.getRange(lines.length - 8, lines.length).join('\n'),
      equalsIgnoringHashCodes(
        'The following RenderObject was being processed when the exception was fired:\n'
        '  TestReentrantPaintingErrorRenderBox#00000:\n'
        '  parentData: <none>\n'
        '  constraints: BoxConstraints(w=800.0, h=600.0)\n'
        '  size: Size(100.0, 100.0)\n'
        'This RenderObject has no descendants.\n'
        '═════════════════════════════════════════════════════════════════\n',
      ),
    );
  });

  test('needsCompositingBitsUpdate paint error', () {
    late FlutterError flutterError;
    final RenderBox root = RenderRepaintBoundary(child: RenderSizedBox(const Size(100, 100)));
    try {
      layout(root);
      PaintingContext.repaintCompositedChild(root, debugAlsoPaintedParent: true);
    } on FlutterError catch (exception) {
      flutterError = exception;
    }

    expect(flutterError, isNotNull);
    // The lines in the middle of the error message contain the stack trace
    // which will change depending on where the test is run.
    expect(
      flutterError.toStringDeep(),
      equalsIgnoringHashCodes(
        'FlutterError\n'
        '   Tried to paint a RenderObject before its compositing bits were\n'
        '   updated.\n'
        '   The following RenderObject was marked as having dirty compositing bits at the time that it was painted:\n'
        '     RenderRepaintBoundary#00000 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE:\n'
        '     needs compositing\n'
        '     parentData: <none>\n'
        '     constraints: BoxConstraints(w=800.0, h=600.0)\n'
        '     layer: OffsetLayer#00000 DETACHED\n'
        '     size: Size(800.0, 600.0)\n'
        '     metrics: 0.0% useful (1 bad vs 0 good)\n'
        '     diagnosis: insufficient data to draw conclusion (less than five\n'
        '       repaints)\n'
        '   A RenderObject that still has dirty compositing bits cannot be\n'
        '   painted because this indicates that the tree has not yet been\n'
        '   properly configured for creating the layer tree.\n'
        '   This usually indicates an error in the Flutter framework itself.\n',
      ),
    );
    expect(
      flutterError.diagnostics.singleWhere((DiagnosticsNode node) => node.level == DiagnosticLevel.hint).toString(),
      'This usually indicates an error in the Flutter framework itself.',
    );
  });
}

class TestReentrantPaintingErrorRenderBox extends RenderBox {
  @override
  void paint(PaintingContext context, Offset offset) {
    // Cause a reentrant painting bug that would show up as a stack overflow if
    // it was not for debugging checks in RenderObject.
    context.paintChild(this, offset);
  }

  @override
  void performLayout() {
    size = const Size(100, 100);
  }
}
