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

import 'rendering_tester.dart';

void main() {
  test('nested repaint boundaries - smoke test', () {
    RenderOpacity a, b, c;
    a = RenderOpacity(
      opacity: 1.0,
      child: RenderRepaintBoundary(
        child: b = RenderOpacity(
          opacity: 1.0,
          child: RenderRepaintBoundary(
            child: c = RenderOpacity(
              opacity: 1.0
            )
          ),
        ),
      ),
    );
    layout(a, phase: EnginePhase.flushSemantics);
    c.opacity = 0.9;
    pumpFrame(phase: EnginePhase.flushSemantics);
    a.opacity = 0.8;
    c.opacity = 0.8;
    pumpFrame(phase: EnginePhase.flushSemantics);
    a.opacity = 0.7;
    b.opacity = 0.7;
    c.opacity = 0.7;
    pumpFrame(phase: EnginePhase.flushSemantics);
  });

  test('Repaint boundary can get new parent after markNeedsCompositingBitsUpdate', () {
    // Regression test for https://github.com/flutter/flutter/issues/24029.

    final RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();
    layout(repaintBoundary, phase: EnginePhase.flushSemantics);

    repaintBoundary.markNeedsCompositingBitsUpdate();

    renderer.renderView.child = null;
    final RenderPadding padding = RenderPadding(
      padding: const EdgeInsets.all(50),
    );
    renderer.renderView.child = padding;
    padding.child = repaintBoundary;
    pumpFrame(phase: EnginePhase.flushSemantics);
  });

  test('Framework creates an OffsetLayer for a repaint boundary', () {
    final _TestRepaintBoundary repaintBoundary = _TestRepaintBoundary();
    final RenderOpacity opacity = RenderOpacity(
      opacity: 1.0,
      child: repaintBoundary,
    );
    layout(opacity, phase: EnginePhase.flushSemantics);
    expect(repaintBoundary.debugLayer, isA<OffsetLayer>());
  });

  test('Framework does not create an OffsetLayer for a non-repaint boundary', () {
    final _TestNonCompositedBox nonCompositedBox = _TestNonCompositedBox();
    final RenderOpacity opacity = RenderOpacity(
      opacity: 1.0,
      child: nonCompositedBox,
    );
    layout(opacity, phase: EnginePhase.flushSemantics);
    expect(nonCompositedBox.debugLayer, null);
  });

  test('Framework allows a non-repaint boundary to create own layer', () {
    final _TestCompositedBox compositedBox = _TestCompositedBox();
    final RenderOpacity opacity = RenderOpacity(
      opacity: 1.0,
      child: compositedBox,
    );
    layout(opacity, phase: EnginePhase.flushSemantics);
    expect(compositedBox.debugLayer, isA<OpacityLayer>());
  });

  test('Framework ensures repaint boundary layer is not overwritten', () {
    final _TestRepaintBoundaryThatOverwritesItsLayer faultyRenderObject = _TestRepaintBoundaryThatOverwritesItsLayer();
    final RenderOpacity opacity = RenderOpacity(
      opacity: 1.0,
      child: faultyRenderObject,
    );

    FlutterErrorDetails error;
    layout(opacity, phase: EnginePhase.flushSemantics, onErrors: () {
      error = renderer.takeFlutterErrorDetails();
    });
    expect('${error.exception}', contains('Attempted to set a layer to a repaint boundary render object.'));
  });
}

// A plain render object that's a repaint boundary.
class _TestRepaintBoundary extends RenderBox {
  @override
  bool get isRepaintBoundary => true;

  @override
  void performLayout() {
    size = constraints.smallest;
  }
}

// A render object that's a repaint boundary and (incorrectly) creates its own layer.
class _TestRepaintBoundaryThatOverwritesItsLayer extends RenderBox {
  @override
  bool get isRepaintBoundary => true;

  @override
  void performLayout() {
    size = constraints.smallest;
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    layer = OpacityLayer(alpha: 50);
  }
}

// A render object that's neither a repaint boundary nor creates its own layer.
class _TestNonCompositedBox extends RenderBox {
  @override
  bool get isRepaintBoundary => false;

  @override
  void performLayout() {
    size = constraints.smallest;
  }
}

// A render object that's not a repaint boundary but creates its own layer.
class _TestCompositedBox extends RenderBox {
  @override
  bool get isRepaintBoundary => false;

  @override
  void performLayout() {
    size = constraints.smallest;
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    layer = OpacityLayer(alpha: 50);
  }
}
