// 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';

class RenderFixedSize extends RenderBox {
  double dimension = 100.0;

  void grow() {
    dimension *= 2.0;
    markNeedsLayout();
  }

  @override
  double computeMinIntrinsicWidth(double height) => dimension;
  @override
  double computeMaxIntrinsicWidth(double height) => dimension;
  @override
  double computeMinIntrinsicHeight(double width) => dimension;
  @override
  double computeMaxIntrinsicHeight(double width) => dimension;

  @override
  void performLayout() {
    size = Size.square(dimension);
  }
}

class RenderParentSize extends RenderProxyBox {
  RenderParentSize({ required RenderBox child }) : super(child);

  @override
  bool get sizedByParent => true;

  @override
  void performResize() {
    size = constraints.biggest;
  }

  @override
  void performLayout() {
    child!.layout(constraints);
  }
}

class RenderIntrinsicSize extends RenderProxyBox {
  RenderIntrinsicSize({ required RenderBox child }) : super(child);

  @override
  void performLayout() {
    child!.layout(constraints);
    size = Size(
      child!.getMinIntrinsicWidth(double.infinity),
      child!.getMinIntrinsicHeight(double.infinity),
    );
  }
}

class RenderInvalidIntrinsics extends RenderBox {
  @override
  bool get sizedByParent => true;
  @override
  double computeMinIntrinsicWidth(double height) => -1;
  @override
  double computeMaxIntrinsicWidth(double height) => -1;
  @override
  double computeMinIntrinsicHeight(double width) => -1;
  @override
  double computeMaxIntrinsicHeight(double width) => -1;
  @override
  Size computeDryLayout(BoxConstraints constraints) => Size.zero;
}

void main() {
  TestRenderingFlutterBinding.ensureInitialized();

  test('Whether using intrinsics means you get hooked into layout', () {
    RenderBox root;
    RenderFixedSize inner;
    layout(
      root = RenderIntrinsicSize(
        child: RenderParentSize(
          child: inner = RenderFixedSize(),
        ),
      ),
      constraints: const BoxConstraints(
        maxWidth: 1000.0,
        maxHeight: 1000.0,
      ),
    );
    expect(root.size, equals(inner.size));

    inner.grow();
    pumpFrame();
    expect(root.size, equals(inner.size));
  });

  test('Parent returns correct intrinsics', () {
    RenderParentSize parent;
    RenderFixedSize inner;

    layout(
      RenderIntrinsicSize(
        child: parent = RenderParentSize(
          child: inner = RenderFixedSize(),
        ),
      ),
      constraints: const BoxConstraints(
        maxWidth: 1000.0,
        maxHeight: 1000.0,
      ),
    );

    _expectIntrinsicDimensions(parent, 100);

    inner.grow();
    pumpFrame();

    _expectIntrinsicDimensions(parent, 200);
  });

  test('Intrinsic checks are turned on', () async {
    final List<FlutterErrorDetails> errorDetails = <FlutterErrorDetails>[];
    layout(
      RenderInvalidIntrinsics(),
      constraints: const BoxConstraints(
        maxWidth: 1000.0,
        maxHeight: 1000.0,
      ),
      onErrors: () {
        errorDetails.addAll(TestRenderingFlutterBinding.instance.takeAllFlutterErrorDetails());
      },
    );

    expect(errorDetails, isNotEmpty);
    expect(
      errorDetails.map((FlutterErrorDetails details) => details.toString()),
      everyElement(contains('violate the intrinsic protocol')),
    );
  });
}

/// Asserts that all unbounded intrinsic dimensions for [object] match
/// [dimension].
void _expectIntrinsicDimensions(RenderBox object, double dimension) {
  expect(object.getMinIntrinsicWidth(double.infinity), equals(dimension));
  expect(object.getMaxIntrinsicWidth(double.infinity), equals(dimension));
  expect(object.getMinIntrinsicHeight(double.infinity), equals(dimension));
  expect(object.getMaxIntrinsicHeight(double.infinity), equals(dimension));
}
