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

import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

void main() {
  testWidgets('Positioned constructors', (WidgetTester tester) async {
    final Widget child = Container();
    final Positioned a = Positioned(
      left: 101.0,
      right: 201.0,
      top: 301.0,
      bottom: 401.0,
      child: child,
    );
    expect(a.left, 101.0);
    expect(a.right, 201.0);
    expect(a.top, 301.0);
    expect(a.bottom, 401.0);
    expect(a.width, null);
    expect(a.height, null);
    final Positioned b = Positioned.fromRect(
      rect: const Rect.fromLTRB(
        102.0,
        302.0,
        202.0,
        502.0,
      ),
      child: child,
    );
    expect(b.left, 102.0);
    expect(b.right, null);
    expect(b.top, 302.0);
    expect(b.bottom, null);
    expect(b.width, 100.0);
    expect(b.height, 200.0);
    final Positioned c = Positioned.fromRelativeRect(
      rect: const RelativeRect.fromLTRB(
        103.0,
        303.0,
        203.0,
        403.0,
      ),
      child: child,
    );
    expect(c.left, 103.0);
    expect(c.right, 203.0);
    expect(c.top, 303.0);
    expect(c.bottom, 403.0);
    expect(c.width, null);
    expect(c.height, null);
  });

  testWidgets('Can animate position data', (WidgetTester tester) async {
    final RelativeRectTween rect = RelativeRectTween(
      begin: RelativeRect.fromRect(
        const Rect.fromLTRB(10.0, 20.0, 20.0, 30.0),
        const Rect.fromLTRB(0.0, 10.0, 100.0, 110.0),
      ),
      end: RelativeRect.fromRect(
        const Rect.fromLTRB(80.0, 90.0, 90.0, 100.0),
        const Rect.fromLTRB(0.0, 10.0, 100.0, 110.0),
      ),
    );
    final AnimationController controller = AnimationController(
      duration: const Duration(seconds: 10),
      vsync: tester,
    );
    final List<Size> sizes = <Size>[];
    final List<Offset> positions = <Offset>[];
    final GlobalKey key = GlobalKey();

    void recordMetrics() {
      final RenderBox box = key.currentContext.findRenderObject() as RenderBox;
      final BoxParentData boxParentData = box.parentData as BoxParentData;
      sizes.add(box.size);
      positions.add(boxParentData.offset);
    }

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Container(
            height: 100.0,
            width: 100.0,
            child: Stack(
              children: <Widget>[
                PositionedTransition(
                  rect: rect.animate(controller),
                  child: Container(
                    key: key,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    ); // t=0
    recordMetrics();
    final Completer<void> completer = Completer<void>();
    controller.forward().whenComplete(completer.complete);
    expect(completer.isCompleted, isFalse);
    await tester.pump(); // t=0 again
    expect(completer.isCompleted, isFalse);
    recordMetrics();
    await tester.pump(const Duration(seconds: 1)); // t=1
    expect(completer.isCompleted, isFalse);
    recordMetrics();
    await tester.pump(const Duration(seconds: 1)); // t=2
    expect(completer.isCompleted, isFalse);
    recordMetrics();
    await tester.pump(const Duration(seconds: 3)); // t=5
    expect(completer.isCompleted, isFalse);
    recordMetrics();
    await tester.pump(const Duration(seconds: 5)); // t=10
    expect(completer.isCompleted, isFalse);
    recordMetrics();

    expect(sizes, equals(<Size>[const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0)]));
    expect(positions, equals(<Offset>[const Offset(10.0, 10.0), const Offset(10.0, 10.0), const Offset(17.0, 17.0), const Offset(24.0, 24.0), const Offset(45.0, 45.0), const Offset(80.0, 80.0)]));

    controller.stop(canceled: false);
    await tester.pump();
    expect(completer.isCompleted, isTrue);
  });
}
