// 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 BoxConstraints 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 RenderView view = RenderView(
        configuration: createViewConfiguration(),
        view: RendererBinding.instance.platformDispatcher.views.single,
      );
      final PipelineOwner 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 RenderView view = RenderView(
        configuration: createViewConfiguration(size: const Size(100.0, 100.0)),
        view: RendererBinding.instance.platformDispatcher.views.single,
      );
      final PipelineOwner 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 RenderView 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 BoxConstraints constraints = BoxConstraints(minWidth: 1, maxWidth: 2, minHeight: 3, maxHeight: 4);
    const double devicePixelRatio = 3.0;
    final ViewConfiguration config = ViewConfiguration(
      logicalConstraints: constraints,
      physicalConstraints: constraints * devicePixelRatio,
      devicePixelRatio: devicePixelRatio,
    );

    // Configuration set via setter.
    final RenderView 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 RenderView 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,
    );
  }
}
