// 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_test/flutter_test.dart';

import 'rendering_tester.dart';

void main() {
  TestRenderingFlutterBinding.ensureInitialized();

  // Create non-const instances, otherwise tests pass even if the
  // operator override is incorrect.
  ViewConfiguration createViewConfiguration({
    Size size = const Size(20, 20),
    double devicePixelRatio = 2.0,
  }) {
    final constraints = BoxConstraints.tight(size);
    return ViewConfiguration(
      logicalConstraints: constraints,
      physicalConstraints: constraints * devicePixelRatio,
      devicePixelRatio: devicePixelRatio,
    );
  }

  group('RenderView', () {
    test('accounts for device pixel ratio in paintBounds', () {
      layout(RenderAspectRatio(aspectRatio: 1.0));
      pumpFrame();
      final Size logicalSize = TestRenderingFlutterBinding.instance.renderView.size;
      final double devicePixelRatio =
          TestRenderingFlutterBinding.instance.renderView.configuration.devicePixelRatio;
      final Size physicalSize = logicalSize * devicePixelRatio;
      expect(
        TestRenderingFlutterBinding.instance.renderView.paintBounds,
        Offset.zero & physicalSize,
      );
    });

    test('does not replace the root layer unnecessarily', () {
      final view = RenderView(
        configuration: createViewConfiguration(),
        view: RendererBinding.instance.platformDispatcher.views.single,
      );
      final owner = PipelineOwner();
      view.attach(owner);
      view.prepareInitialFrame();
      final ContainerLayer firstLayer = view.debugLayer!;
      view.configuration = createViewConfiguration();
      expect(identical(view.debugLayer, firstLayer), true);

      view.configuration = createViewConfiguration(devicePixelRatio: 5.0);
      expect(identical(view.debugLayer, firstLayer), false);
    });

    test('does not replace the root layer unnecessarily when view resizes', () {
      final view = RenderView(
        configuration: createViewConfiguration(size: const Size(100.0, 100.0)),
        view: RendererBinding.instance.platformDispatcher.views.single,
      );
      final owner = PipelineOwner();
      view.attach(owner);
      view.prepareInitialFrame();
      final ContainerLayer firstLayer = view.debugLayer!;
      view.configuration = createViewConfiguration(size: const Size(100.0, 1117.0));
      expect(identical(view.debugLayer, firstLayer), true);
    });
  });

  test('ViewConfiguration == and hashCode', () {
    final ViewConfiguration viewConfigurationA = createViewConfiguration();
    final ViewConfiguration viewConfigurationB = createViewConfiguration();
    final ViewConfiguration viewConfigurationC = createViewConfiguration(devicePixelRatio: 3.0);

    expect(viewConfigurationA == viewConfigurationB, true);
    expect(viewConfigurationA != viewConfigurationC, true);
    expect(viewConfigurationA.hashCode, viewConfigurationB.hashCode);
    expect(viewConfigurationA.hashCode != viewConfigurationC.hashCode, true);
  });

  test('invokes DebugPaintCallback', () {
    final PaintPattern paintsOrangeRect = paints..rect(color: orange, rect: orangeRect);
    final PaintPattern paintsGreenRect = paints..rect(color: green, rect: greenRect);
    final PaintPattern paintOrangeAndGreenRect = paints
      ..rect(color: orange, rect: orangeRect)
      ..rect(color: green, rect: greenRect);
    void paintCallback(PaintingContext context, Offset offset, RenderView renderView) {
      context.canvas.drawRect(greenRect, Paint()..color = green);
    }

    layout(TestRenderObject());
    expect(TestRenderingFlutterBinding.instance.renderView, paintsOrangeRect);
    expect(TestRenderingFlutterBinding.instance.renderView, isNot(paintsGreenRect));

    RenderView.debugAddPaintCallback(paintCallback);
    expect(TestRenderingFlutterBinding.instance.renderView, paintOrangeAndGreenRect);

    RenderView.debugRemovePaintCallback(paintCallback);
    expect(TestRenderingFlutterBinding.instance.renderView, paintsOrangeRect);
    expect(TestRenderingFlutterBinding.instance.renderView, isNot(paintsGreenRect));
  });

  test(
    'Config can be set and changed after instantiation without calling prepareInitialFrame first',
    () {
      final view = RenderView(view: RendererBinding.instance.platformDispatcher.views.single);
      view.configuration = ViewConfiguration(
        logicalConstraints: BoxConstraints.tight(const Size(100, 200)),
        devicePixelRatio: 3.0,
      );
      view.configuration = ViewConfiguration(
        logicalConstraints: BoxConstraints.tight(const Size(200, 300)),
        devicePixelRatio: 2.0,
      );
      PipelineOwner().rootNode = view;
      view.prepareInitialFrame();
    },
  );

  test('Constraints are derived from configuration', () {
    const constraints = BoxConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4);
    const devicePixelRatio = 3.0;
    final config = ViewConfiguration(
      logicalConstraints: constraints,
      physicalConstraints: constraints * devicePixelRatio,
      devicePixelRatio: devicePixelRatio,
    );

    // Configuration set via setter.
    final view = RenderView(view: RendererBinding.instance.platformDispatcher.views.single);
    expect(
      () => view.constraints,
      throwsA(
        isA<StateError>().having(
          (StateError e) => e.message,
          'message',
          contains('RenderView has not been given a configuration yet'),
        ),
      ),
    );
    view.configuration = config;
    expect(view.constraints, constraints);

    // Configuration set in constructor.
    final view2 = RenderView(
      view: RendererBinding.instance.platformDispatcher.views.single,
      configuration: config,
    );
    expect(view2.constraints, constraints);
  });
}

const Color orange = Color(0xFFFF9000);
const Color green = Color(0xFF0FF900);
const Rect orangeRect = Rect.fromLTWH(10, 10, 50, 75);
const Rect greenRect = Rect.fromLTWH(20, 20, 100, 150);

class TestRenderObject extends RenderBox {
  @override
  void performLayout() {
    size = constraints.biggest;
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    context.canvas.drawRect(orangeRect, Paint()..color = orange);
  }
}
