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

class TestCustomPainter extends CustomPainter {
  TestCustomPainter({ required this.log, this.name });

  final List<String?> log;
  final String? name;

  @override
  void paint(Canvas canvas, Size size) {
    log.add(name);
  }

  @override
  bool shouldRepaint(TestCustomPainter oldPainter) => true;
}

class TestCustomPainterWithCustomSemanticsBuilder extends TestCustomPainter {
  TestCustomPainterWithCustomSemanticsBuilder() : super(log: <String>[]);

  @override
  SemanticsBuilderCallback get semanticsBuilder => (Size size) {
    const Key key = Key('0');
    const Rect rect = Rect.zero;
    const SemanticsProperties semanticsProperties = SemanticsProperties();
    return <CustomPainterSemantics>[
      const CustomPainterSemantics(key: key, rect: rect, properties: semanticsProperties),
      const CustomPainterSemantics(key: key, rect: rect, properties: semanticsProperties),
    ];
  };
}

class MockCanvas extends Fake implements Canvas {
  int saveCount = 0;
  int saveCountDelta = 1;

  @override
  int getSaveCount() {
    return saveCount += saveCountDelta;
  }

  @override
  void save() { }
}

class MockPaintingContext extends Fake implements PaintingContext {
  @override
  final MockCanvas canvas = MockCanvas();
}

void main() {
  testWidgets('Control test for custom painting', (WidgetTester tester) async {
    final List<String?> log = <String?>[];
    await tester.pumpWidget(CustomPaint(
      painter: TestCustomPainter(
        log: log,
        name: 'background',
      ),
      foregroundPainter: TestCustomPainter(
        log: log,
        name: 'foreground',
      ),
      child: CustomPaint(
        painter: TestCustomPainter(
          log: log,
          name: 'child',
        ),
      ),
    ));

    expect(log, equals(<String>['background', 'child', 'foreground']));
  });

  testWidgets('Throws FlutterError on custom painter incorrect restore/save calls', (WidgetTester tester) async {
    final GlobalKey target = GlobalKey();
    final List<String?> log = <String?>[];
    await tester.pumpWidget(CustomPaint(
      key: target,
      isComplex: true,
      painter: TestCustomPainter(log: log),
    ));
    final RenderCustomPaint renderCustom = target.currentContext!.findRenderObject()! as RenderCustomPaint;
    final MockPaintingContext paintingContext = MockPaintingContext();
    final MockCanvas canvas = paintingContext.canvas;

    FlutterError getError() {
      late FlutterError error;
      try {
        renderCustom.paint(paintingContext, Offset.zero);
      } on FlutterError catch (e) {
        error = e;
      }
      return error;
    }

    FlutterError error = getError();
    expect(error.toStringDeep(), equalsIgnoringHashCodes(
      'FlutterError\n'
      '   The TestCustomPainter#00000() custom painter called canvas.save()\n'
      '   or canvas.saveLayer() at least 1 more time than it called\n'
      '   canvas.restore().\n'
      '   This leaves the canvas in an inconsistent state and will probably\n'
      '   result in a broken display.\n'
      '   You must pair each call to save()/saveLayer() with a later\n'
      '   matching call to restore().\n',
    ));

    canvas.saveCountDelta = -1;
    error = getError();
    expect(error.toStringDeep(), equalsIgnoringHashCodes(
      'FlutterError\n'
      '   The TestCustomPainter#00000() custom painter called\n'
      '   canvas.restore() 1 more time than it called canvas.save() or\n'
      '   canvas.saveLayer().\n'
      '   This leaves the canvas in an inconsistent state and will result\n'
      '   in a broken display.\n'
      '   You should only call restore() if you first called save() or\n'
      '   saveLayer().\n',
    ));

    canvas.saveCountDelta = 2;
    error = getError();
    expect(error.toStringDeep(), contains('2 more times'));

    canvas.saveCountDelta = -2;
    error = getError();
    expect(error.toStringDeep(), contains('2 more times'));
  });

  testWidgets('CustomPaint sizing', (WidgetTester tester) async {
    final GlobalKey target = GlobalKey();

    await tester.pumpWidget(Center(
      child: CustomPaint(key: target),
    ));
    expect(target.currentContext!.size, Size.zero);

    await tester.pumpWidget(Center(
      child: CustomPaint(key: target, child: Container()),
    ));
    expect(target.currentContext!.size, const Size(800.0, 600.0));

    await tester.pumpWidget(Center(
      child: CustomPaint(key: target, size: const Size(20.0, 20.0)),
    ));
    expect(target.currentContext!.size, const Size(20.0, 20.0));

    await tester.pumpWidget(Center(
      child: CustomPaint(key: target, size: const Size(2000.0, 100.0)),
    ));
    expect(target.currentContext!.size, const Size(800.0, 100.0));

    await tester.pumpWidget(Center(
      child: CustomPaint(key: target, size: Size.zero, child: Container()),
    ));
    expect(target.currentContext!.size, const Size(800.0, 600.0));

    await tester.pumpWidget(Center(
      child: CustomPaint(key: target, child: const SizedBox(height: 0.0, width: 0.0)),
    ));
    expect(target.currentContext!.size, Size.zero);

  });

  testWidgets('Raster cache hints', (WidgetTester tester) async {
    final GlobalKey target = GlobalKey();

    final List<String?> log = <String?>[];
    await tester.pumpWidget(CustomPaint(
      key: target,
      isComplex: true,
      painter: TestCustomPainter(log: log),
    ));
    RenderCustomPaint renderCustom = target.currentContext!.findRenderObject()! as RenderCustomPaint;
    expect(renderCustom.isComplex, true);
    expect(renderCustom.willChange, false);

    await tester.pumpWidget(CustomPaint(
      key: target,
      willChange: true,
      foregroundPainter: TestCustomPainter(log: log),
    ));
    renderCustom = target.currentContext!.findRenderObject()! as RenderCustomPaint;
    expect(renderCustom.isComplex, false);
    expect(renderCustom.willChange, true);
  });

  test('Raster cache hints cannot be set with null painters', () {
    expect(() => CustomPaint(isComplex: true), throwsAssertionError);
    expect(() => CustomPaint(willChange: true), throwsAssertionError);
  });

  test('RenderCustomPaint consults preferred size for intrinsics when it has no child', () {
    final RenderCustomPaint inner = RenderCustomPaint(preferredSize: const Size(20, 30));
    expect(inner.getMinIntrinsicWidth(double.infinity), 20);
    expect(inner.getMaxIntrinsicWidth(double.infinity), 20);
    expect(inner.getMinIntrinsicHeight(double.infinity), 30);
    expect(inner.getMaxIntrinsicHeight(double.infinity), 30);
  });

  test('RenderCustomPaint does not return infinity for its intrinsics', () {
    final RenderCustomPaint inner = RenderCustomPaint(preferredSize: Size.infinite);
    expect(inner.getMinIntrinsicWidth(double.infinity), 0);
    expect(inner.getMaxIntrinsicWidth(double.infinity), 0);
    expect(inner.getMinIntrinsicHeight(double.infinity), 0);
    expect(inner.getMaxIntrinsicHeight(double.infinity), 0);
  });
}
