// 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 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:vector_math/vector_math_64.dart';

void main() {
  test('ContainerLayer.findAllAnnotations returns all results from its children', () {
    final Layer root = _Layers(
      ContainerLayer(),
      children: <Object>[
        _TestAnnotatedLayer(1, opaque: false),
        _TestAnnotatedLayer(2, opaque: false),
        _TestAnnotatedLayer(3, opaque: false),
      ]
    ).build();

    expect(
      root.findAllAnnotations<int>(Offset.zero).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 3, localPosition: Offset.zero),
        const AnnotationEntry<int>(annotation: 2, localPosition: Offset.zero),
        const AnnotationEntry<int>(annotation: 1, localPosition: Offset.zero),
      ]),
    );
  });

  test('ContainerLayer.find returns the first result from its children', () {
    final Layer root = _Layers(
      ContainerLayer(),
      children: <Object>[
        _TestAnnotatedLayer(1, opaque: false),
        _TestAnnotatedLayer(2, opaque: false),
        _TestAnnotatedLayer(3, opaque: false),
      ]
    ).build();

    final int result = root.find<int>(Offset.zero);
    expect(result, 3);
  });

  test('ContainerLayer.findAllAnnotations returns empty result when finding nothing', () {
    final Layer root = _Layers(
      ContainerLayer(),
      children: <Object>[
        _TestAnnotatedLayer(1, opaque: false),
        _TestAnnotatedLayer(2, opaque: false),
        _TestAnnotatedLayer(3, opaque: false),
      ]
    ).build();

    expect(root.findAllAnnotations<double>(Offset.zero).entries.isEmpty, isTrue);
  });

  test('ContainerLayer.find returns null when finding nothing', () {
    final Layer root = _Layers(
      ContainerLayer(),
      children: <Object>[
        _TestAnnotatedLayer(1, opaque: false),
        _TestAnnotatedLayer(2, opaque: false),
        _TestAnnotatedLayer(3, opaque: false),
      ]
    ).build();

    expect(root.find<double>(Offset.zero), isNull);
  });

  test('ContainerLayer.findAllAnnotations stops at the first opaque child', () {
    final Layer root = _Layers(
      ContainerLayer(),
      children: <Object>[
        _TestAnnotatedLayer(1, opaque: false),
        _TestAnnotatedLayer(2, opaque: true),
        _TestAnnotatedLayer(3, opaque: false),
      ]
    ).build();

    expect(
      root.findAllAnnotations<int>(Offset.zero).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 3, localPosition: Offset(0, 0)),
        const AnnotationEntry<int>(annotation: 2, localPosition: Offset(0, 0)),
      ]),
    );
  });

  test("ContainerLayer.findAllAnnotations returns children's opacity (true)", () {
    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        ContainerLayer(),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: true),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(Offset.zero).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: Offset(0, 0)),
      ]),
    );
  });

  test("ContainerLayer.findAllAnnotations returns children's opacity (false)", () {
    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        ContainerLayer(),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false),
        ],
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(Offset.zero).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: Offset(0, 0)),
        const AnnotationEntry<int>(annotation: 1000, localPosition: Offset(0, 0)),
      ]),
    );
  });

  test('ContainerLayer.findAllAnnotations returns false as opacity when finding nothing', () {
    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        ContainerLayer(),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false, size: Size.zero),
        ],
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(Offset.zero).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: Offset(0, 0)),
      ]),
    );
  });

  test('OffsetLayer.findAllAnnotations respects offset', () {
    const Offset insidePosition = Offset(-5, 5);
    const Offset outsidePosition = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        OffsetLayer(offset: const Offset(-10, 0)),
        children: <Object>[
          _TestAnnotatedLayer(1, opaque: true, size: const Size(10, 10)),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(insidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1, localPosition: Offset(5, 5)),
      ]),
    );
    expect(
      root.findAllAnnotations<int>(outsidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: Offset(5, 5)),
      ]),
    );
  });

  test('ClipRectLayer.findAllAnnotations respects clipRect', () {
    const Offset insidePosition = Offset(11, 11);
    const Offset outsidePosition = Offset(19, 19);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        ClipRectLayer(clipRect: const Offset(10, 10) & const Size(5, 5)),
        children: <Object>[
          _TestAnnotatedLayer(
            1,
            opaque: true,
            size: const Size(10, 10),
            offset: const Offset(10, 10),
          ),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(insidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1, localPosition: insidePosition),
      ]),
    );
    expect(
      root.findAllAnnotations<int>(outsidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: outsidePosition),
      ]),
    );
  });

  test('ClipRRectLayer.findAllAnnotations respects clipRRect', () {
    // For a curve of radius 4 centered at (4, 4),
    // location (1, 1) is outside, while (2, 2) is inside.
    // Here we shift this RRect by (10, 10).
    final RRect rrect = RRect.fromRectAndRadius(
      const Offset(10, 10) & const Size(10, 10),
      const Radius.circular(4),
    );
    const Offset insidePosition = Offset(12, 12);
    const Offset outsidePosition = Offset(11, 11);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        ClipRRectLayer(clipRRect: rrect),
        children: <Object>[
          _TestAnnotatedLayer(
            1,
            opaque: true,
            size: const Size(10, 10),
            offset: const Offset(10, 10),
          ),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(insidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1, localPosition: insidePosition),
      ]),
    );
    expect(
      root.findAllAnnotations<int>(outsidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: outsidePosition),
      ]),
    );
  });

  test('ClipPathLayer.findAllAnnotations respects clipPath', () {
    // For this triangle, location (1, 1) is inside, while (2, 2) is outside.
    //         2
    //    —————
    //    |  /
    //    | /
    // 2  |/
    final Path originalPath = Path();
    originalPath.lineTo(2, 0);
    originalPath.lineTo(0, 2);
    originalPath.close();
    // Shift this clip path by (10, 10).
    final Path path = originalPath.shift(const Offset(10, 10));
    const Offset insidePosition = Offset(11, 11);
    const Offset outsidePosition = Offset(12, 12);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        ClipPathLayer(clipPath: path),
        children: <Object>[
          _TestAnnotatedLayer(
            1,
            opaque: true,
            size: const Size(10, 10),
            offset: const Offset(10, 10),
          ),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(insidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1, localPosition: insidePosition),
      ]),
    );
    expect(
      root.findAllAnnotations<int>(outsidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: outsidePosition),
      ]),
    );
  });

  test('TransformLayer.findAllAnnotations respects transform', () {
    // Matrix `transform` enlarges the target by (2x, 4x), then shift it by
    // (10, 20).
    final Matrix4 transform = Matrix4.diagonal3Values(2, 4, 1)
      ..setTranslation(Vector3(10, 20, 0));
    // The original region is Offset(10, 10) & Size(10, 10)
    // The transformed region is Offset(30, 60) & Size(20, 40)
    const Offset insidePosition = Offset(40, 80);
    const Offset outsidePosition = Offset(20, 40);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        TransformLayer(transform: transform),
        children: <Object>[
          _TestAnnotatedLayer(
            1,
            opaque: true,
            size: const Size(10, 10),
            offset: const Offset(10, 10),
          ),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(insidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1, localPosition: Offset(15, 15)),
      ]),
    );
    expect(
      root.findAllAnnotations<int>(outsidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: outsidePosition),
      ]),
    );
  });

  test('TransformLayer.findAllAnnotations correctly transforms with perspective', () {
    // Test the 4 corners of a transformed annotated region.
    final Matrix4 transform = Matrix4.identity()
      ..setEntry(3, 2, 0.005)
      ..rotateX(-0.2)
      ..rotateY(0.2);

    final Layer root = _withBackgroundAnnotation(0,
      _Layers(
        TransformLayer(transform: transform),
        children: <Object>[
          _TestAnnotatedLayer(
            1,
            opaque: true,
            size: const Size(30, 40),
            offset: const Offset(10, 20),
          ),
        ]
      ).build(),
    );

    void expectOneAnnotation({
      @required Offset globalPosition,
      @required int value,
      @required Offset localPosition,
    }) {
      expect(
        root.findAllAnnotations<int>(globalPosition).entries.toList(),
        _equalToAnnotationResult<int>(
          <AnnotationEntry<int>>[
            AnnotationEntry<int>(annotation: value, localPosition: localPosition),
          ],
          maxCoordinateRelativeDiff: 0.005,
        ),
      );
    }

    expectOneAnnotation(
      globalPosition: const Offset(10.0, 19.7),
      value: 0,
      localPosition: const Offset(10.0, 19.7),
    );
    expectOneAnnotation(
      globalPosition: const Offset(10.1, 19.8),
      value: 1,
      localPosition: const Offset(10.0, 20.0),
    );

    expectOneAnnotation(
      globalPosition: const Offset(10.5, 62.8),
      value: 0,
      localPosition: const Offset(10.5, 62.8),
    );
    expectOneAnnotation(
      globalPosition: const Offset(10.6, 62.7),
      value: 1,
      localPosition: const Offset(10.1, 59.9),
    );

    expectOneAnnotation(
      globalPosition: const Offset(42.6, 40.8),
      value: 0,
      localPosition: const Offset(42.6, 40.8),
    );
    expectOneAnnotation(
      globalPosition: const Offset(42.5, 40.9),
      value: 1,
      localPosition: const Offset(39.9, 40.0),
    );

    expectOneAnnotation(
      globalPosition: const Offset(43.5, 63.5),
      value: 0,
      localPosition: const Offset(43.5, 63.5),
    );
    expectOneAnnotation(
      globalPosition: const Offset(43.4, 63.4),
      value: 1,
      localPosition: const Offset(39.9, 59.9),
    );
  });

  test('TransformLayer.findAllAnnotations skips when transform is irreversible', () {
    final Matrix4 transform = Matrix4.diagonal3Values(1, 0, 1);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        TransformLayer(transform: transform),
        children: <Object>[
          _TestAnnotatedLayer(1, opaque: true),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(Offset.zero).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: Offset.zero),
      ]),
    );
  });

  test('PhysicalModelLayer.findAllAnnotations respects clipPath', () {
    // For this triangle, location (1, 1) is inside, while (2, 2) is outside.
    //         2
    //    —————
    //    |  /
    //    | /
    // 2  |/
    final Path originalPath = Path();
    originalPath.lineTo(2, 0);
    originalPath.lineTo(0, 2);
    originalPath.close();
    // Shift this clip path by (10, 10).
    final Path path = originalPath.shift(const Offset(10, 10));
    const Offset insidePosition = Offset(11, 11);
    const Offset outsidePosition = Offset(12, 12);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        PhysicalModelLayer(
          clipPath: path,
          elevation: 10,
          color: const Color.fromARGB(0, 0, 0, 0),
          shadowColor: const Color.fromARGB(0, 0, 0, 0),
        ),
        children: <Object>[
          _TestAnnotatedLayer(
            1,
            opaque: true,
            size: const Size(10, 10),
            offset: const Offset(10, 10),
          ),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(insidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1, localPosition: insidePosition),
      ]),
    );
    expect(
      root.findAllAnnotations<int>(outsidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: outsidePosition),
      ]),
    );
  });


  test('LeaderLayer.findAllAnnotations respects offset', () {
    const Offset insidePosition = Offset(-5, 5);
    const Offset outsidePosition = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        LeaderLayer(
          link: LayerLink(),
          offset: const Offset(-10, 0),
        ),
        children: <Object>[
          _TestAnnotatedLayer(1, opaque: true, size: const Size(10, 10)),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(insidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1, localPosition: Offset(5, 5)),
      ]),
    );
    expect(
      root.findAllAnnotations<int>(outsidePosition).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 1000, localPosition: outsidePosition),
      ]),
    );
  });

  test('AnnotatedRegionLayer.findAllAnnotations should append to the list '
    'and return the given opacity (false) during a successful hit', () {
    const Offset position = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(1, opaque: false),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
        const AnnotationEntry<int>(annotation: 1, localPosition: position),
        const AnnotationEntry<int>(annotation: 1000, localPosition: position),
      ]),
    );
  });

  test('AnnotatedRegionLayer.findAllAnnotations should append to the list '
    'and return the given opacity (true) during a successful hit', () {
    const Offset position = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(1, opaque: true),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
        const AnnotationEntry<int>(annotation: 1, localPosition: position),
      ]),
    );
  });

  test('AnnotatedRegionLayer.findAllAnnotations has default opacity as false', () {
    const Offset position = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(1),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
        const AnnotationEntry<int>(annotation: 1, localPosition: position),
        const AnnotationEntry<int>(annotation: 1000, localPosition: position),
      ]),
    );
  });

  test('AnnotatedRegionLayer.findAllAnnotations should still check children and return '
    "children's opacity (false) during a failed hit", () {
    const Offset position = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(1, opaque: true, size: Size.zero),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false),
        ]
      ).build(),
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
        const AnnotationEntry<int>(annotation: 1000, localPosition: position),
      ]),
    );
  });

  test('AnnotatedRegionLayer.findAllAnnotations should still check children and return '
    "children's opacity (true) during a failed hit", () {
    const Offset position = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(1, opaque: false, size: Size.zero),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: true),
        ]
      ).build()
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
      ]),
    );
  });

  test("AnnotatedRegionLayer.findAllAnnotations should not add to children's opacity "
    'during a successful hit if it is not opaque', () {
    const Offset position = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(1, opaque: false),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false),
        ]
      ).build()
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
        const AnnotationEntry<int>(annotation: 1, localPosition: position),
        const AnnotationEntry<int>(annotation: 1000, localPosition: position),
      ]),
    );
  });

  test("AnnotatedRegionLayer.findAllAnnotations should add to children's opacity "
    'during a successful hit if it is opaque', () {
    const Offset position = Offset(5, 5);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(1, opaque: true),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false),
        ]
      ).build()
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
        const AnnotationEntry<int>(annotation: 1, localPosition: position),
      ]),
    );
  });

  test('AnnotatedRegionLayer.findAllAnnotations should clip its annotation '
    'using size and offset (positive)', () {
    // The target position would have fallen outside if not for the offset.
    const Offset position = Offset(100, 100);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(
          1,
          size: const Size(20, 20),
          offset: const Offset(90, 90),
        ),
        children: <Object>[
          _TestAnnotatedLayer(
            2,
            opaque: false,
            // Use this offset to make sure AnnotatedRegionLayer's offset
            // does not affect its children.
            offset: const Offset(20, 20),
            size: const Size(110, 110),
          ),
        ]
      ).build()
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
        const AnnotationEntry<int>(annotation: 1, localPosition: Offset(10, 10)),
        const AnnotationEntry<int>(annotation: 1000, localPosition: position),
      ]),
    );
  });

  test('AnnotatedRegionLayer.findAllAnnotations should clip its annotation '
    'using size and offset (negative)', () {
    // The target position would have fallen inside if not for the offset.
    const Offset position = Offset(10, 10);

    final Layer root = _withBackgroundAnnotation(1000,
      _Layers(
        AnnotatedRegionLayer<int>(
          1,
          size: const Size(20, 20),
          offset: const Offset(90, 90),
        ),
        children: <Object>[
          _TestAnnotatedLayer(2, opaque: false, size: const Size(110, 110)),
        ]
      ).build()
    );

    expect(
      root.findAllAnnotations<int>(position).entries.toList(),
      _equalToAnnotationResult<int>(<AnnotationEntry<int>>[
        const AnnotationEntry<int>(annotation: 2, localPosition: position),
        const AnnotationEntry<int>(annotation: 1000, localPosition: position),
      ]),
    );
  });
}

/// A [ContainerLayer] that contains a stack of layers: `layer` in the front,
/// and another layer annotated with `value` in the back.
///
/// It is a utility function that helps checking the opacity returned by
/// [Layer.findAnnotations].
Layer _withBackgroundAnnotation(int value, Layer layer) {
  return _Layers(
    ContainerLayer(),
    children: <Object>[
      _TestAnnotatedLayer(value, opaque: false),
      layer,
    ],
  ).build();
}

// A utility class that helps building a layer tree.
class _Layers {
  _Layers(this.root, {this.children});

  final ContainerLayer root;
  // Each element must be instance of Layer or _Layers.
  final List<Object> children;
  bool _assigned = false;

  // Build the layer tree by calling each child's `build`, then append children
  // to [root]. Returns the root.
  Layer build() {
    assert(!_assigned);
    _assigned = true;
    if (children != null) {
      for (final Object child in children) {
        Layer layer;
        if (child is Layer) {
          layer = child;
        } else if (child is _Layers) {
          layer = child.build();
        } else {
          assert(false, 'Element of _Layers.children must be instance of Layer or _Layers');
        }
        root.append(layer);
      }
    }
    return root;
  }
}

// This layer's [findAnnotation] can be controlled by the given arguments.
class _TestAnnotatedLayer extends Layer {
  _TestAnnotatedLayer(this.value, {
    @required this.opaque,
    this.offset = Offset.zero,
    this.size,
  });

  // The value added to result in [findAnnotations] during a successful hit.
  final int value;

  // The return value of [findAnnotations] during a successful hit.
  final bool opaque;

  /// The [offset] is optionally used to translate the clip region for the
  /// hit-testing of [find] by [offset].
  ///
  /// If not provided, offset defaults to [Offset.zero].
  ///
  /// Ignored if [size] is not set.
  final Offset offset;

  /// The [size] is optionally used to clip the hit-testing of [find].
  ///
  /// If not provided, all offsets are considered to be contained within this
  /// layer, unless an ancestor layer applies a clip.
  ///
  /// If [offset] is set, then the offset is applied to the size region before
  /// hit testing in [find].
  final Size size;

  @override
  EngineLayer addToScene(SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
    return null;
  }

  // This implementation is hit when the type is `int` and position is within
  // [offset] & [size]. If it is hit, it adds [value] to result and returns
  // [opaque]; otherwise it directly returns false.
  @override
  bool findAnnotations<S>(
    AnnotationResult<S> result,
    Offset localPosition, {
    bool onlyFirst,
  }) {
    if (S != int)
      return false;
    if (size != null && !(offset & size).contains(localPosition))
      return false;
    final Object untypedValue = value;
    final S typedValue = untypedValue as S;
    result.add(AnnotationEntry<S>(annotation: typedValue, localPosition: localPosition));
    return opaque;
  }
}

bool _almostEqual(double a, double b, double maxRelativeDiff) {
  assert(maxRelativeDiff >= 0);
  assert(maxRelativeDiff < 1);
  return (a - b).abs() <= a.abs() * maxRelativeDiff;
}

Matcher _equalToAnnotationResult<T>(
  List<AnnotationEntry<int>> list, {
  double maxCoordinateRelativeDiff = 0,
}) {
  return pairwiseCompare<AnnotationEntry<int>, AnnotationEntry<int>>(
    list,
    (AnnotationEntry<int> a, AnnotationEntry<int> b) {
      return a.annotation == b.annotation
          && _almostEqual(a.localPosition.dx, b.localPosition.dx, maxCoordinateRelativeDiff)
          && _almostEqual(a.localPosition.dy, b.localPosition.dy, maxCoordinateRelativeDiff);
    },
    'equal to',
  );
}
