// 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/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('OverflowBar documented defaults', (WidgetTester tester) async {
    final OverflowBar bar = OverflowBar();
    expect(bar.spacing, 0);
    expect(bar.alignment, null);
    expect(bar.overflowSpacing, 0);
    expect(bar.overflowDirection, VerticalDirection.down);
    expect(bar.textDirection, null);
    expect(bar.clipBehavior, Clip.none);
    expect(bar.children, const <Widget>[]);
  });

  testWidgets('Empty OverflowBar', (WidgetTester tester) async {
    const Size size = Size(16, 24);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: ConstrainedBox(
            constraints: BoxConstraints.tight(size),
            child: OverflowBar(),
          ),
        ),
      ),
    );

    expect(tester.getSize(find.byType(OverflowBar)), size);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: OverflowBar(),
        ),
      ),
    );

    expect(tester.getSize(find.byType(OverflowBar)), Size.zero);
  });

  testWidgets('OverflowBar horizontal layout', (WidgetTester tester) async {
    final Key child1Key = UniqueKey();
    final Key child2Key = UniqueKey();
    final Key child3Key = UniqueKey();

    Widget buildFrame({ required double spacing, required TextDirection textDirection }) {
      return Directionality(
        textDirection: textDirection,
        child: Align(
          alignment: Alignment.topLeft,
          child: OverflowBar(
            spacing: spacing,
            children: <Widget>[
              SizedBox(width: 48, height: 48, key: child1Key),
              SizedBox(width: 64, height: 64, key: child2Key),
              SizedBox(width: 32, height: 32, key: child3Key),
            ],
          ),
        ),
      );
    }

    // Children are vertically centered, start at x=0
    await tester.pumpWidget(buildFrame(spacing: 0, textDirection: TextDirection.ltr));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(0, 8, 48, 56));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(48, 0, 112, 64));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(112, 16, 144, 48));

    // Children are vertically centered, start at x=0
    await tester.pumpWidget(buildFrame(spacing: 10, textDirection: TextDirection.ltr));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(0, 8, 48, 56));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(10.0 + 48, 0, 10.0 + 112, 64));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(10.0 + 112 + 10.0, 16, 10.0 + 10.0 + 144, 48));

    // Children appear in reverse order for RTL
    await tester.pumpWidget(buildFrame(spacing: 0, textDirection: TextDirection.rtl));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(0, 16, 32, 48));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(32, 0, 96, 64));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(96, 8, 144, 56));

    // Children appear in reverse order for RTL
    await tester.pumpWidget(buildFrame(spacing: 10, textDirection: TextDirection.rtl));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(0, 16, 32, 48));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(10.0 + 32, 0, 10.0 + 96, 64));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(10.0 + 96 + 10.0, 8, 10.0 + 10.0 + 144, 56));
  });

  testWidgets('OverflowBar vertical layout', (WidgetTester tester) async {
    final Key child1Key = UniqueKey();
    final Key child2Key = UniqueKey();
    final Key child3Key = UniqueKey();

    Widget buildFrame({
      double overflowSpacing = 0,
      VerticalDirection overflowDirection = VerticalDirection.down,
      OverflowBarAlignment overflowAlignment = OverflowBarAlignment.start,
      TextDirection textDirection = TextDirection.ltr,
    }) {
      return Directionality(
        textDirection: textDirection,
        child: Align(
          alignment: Alignment.topLeft,
          child: ConstrainedBox(
            constraints: BoxConstraints.loose(const Size(100, double.infinity)),
            child: OverflowBar(
              overflowSpacing: overflowSpacing,
              overflowAlignment: overflowAlignment,
              overflowDirection: overflowDirection,
              children: <Widget>[
                SizedBox(width: 48, height: 48, key: child1Key),
                SizedBox(width: 64, height: 64, key: child2Key),
                SizedBox(width: 32, height: 32, key: child3Key),
              ],
            ),
          ),
        ),
      );
    }

    // Children are left aligned
    await tester.pumpWidget(buildFrame());
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(0, 0, 48, 48));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(0, 48, 64, 112));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(0, 112, 32, 144));

    // Children are left aligned
    await tester.pumpWidget(buildFrame(overflowAlignment: OverflowBarAlignment.end, textDirection: TextDirection.rtl));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(0, 0, 48, 48));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(0, 48, 64, 112));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(0, 112, 32, 144));

    // Spaced children are left aligned
    await tester.pumpWidget(buildFrame(overflowSpacing: 10));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(0, 0, 48, 48));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(0, 10.0 + 48, 64, 10.0 + 112));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(0, 10.0 + 112 + 10.0, 32, 10.0 + 10.0 + 144));

    // Left-aligned children appear in reverse order for VerticalDirection.up
    await tester.pumpWidget(buildFrame(overflowDirection: VerticalDirection.up));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(0, 0, 32, 32));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(0, 32, 64, 96));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(0, 96, 48, 144));

    // Left-aligned spaced children appear in reverse order for VerticalDirection.up
    await tester.pumpWidget(buildFrame(overflowSpacing: 10, overflowDirection: VerticalDirection.up));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(0, 0, 32, 32));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(0, 10.0 + 32, 64, 10.0 + 96));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(0, 10.0 + 10.0 + 96, 48, 10.0 + 10.0 + 144));

    // Children are right aligned
    await tester.pumpWidget(buildFrame(overflowAlignment: OverflowBarAlignment.end));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(100.0 - 48, 0, 100, 48));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(100.0 - 64, 48, 100, 112));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(100.0 - 32, 112, 100, 144));

    // Children are right aligned
    await tester.pumpWidget(buildFrame(textDirection: TextDirection.rtl));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(100.0 - 48, 0, 100, 48));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(100.0 - 64, 48, 100, 112));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(100.0 - 32, 112, 100, 144));

    // Children are centered
    await tester.pumpWidget(buildFrame(overflowAlignment: OverflowBarAlignment.center));
    expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(100.0/2.0 - 48/2, 0, 100.0/2.0 + 48/2, 48));
    expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(100.0/2.0 - 64/2, 48, 100.0/2.0 + 64/2, 112));
    expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(100.0/2.0 - 32/2, 112, 100.0/2.0 + 32/2, 144));
  });

  testWidgets('OverflowBar intrinsic width', (WidgetTester tester) async {
    Widget buildFrame({ required double width }) {
      return Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Container(
            width: width,
            alignment: Alignment.topLeft,
            child: IntrinsicWidth(
              child: OverflowBar(
                spacing: 4,
                overflowSpacing: 8,
                children: const <Widget>[
                  SizedBox(width: 48, height: 50),
                  SizedBox(width: 64, height: 25),
                  SizedBox(width: 32, height: 75),
                ],
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame(width: 800));
    expect(tester.getSize(find.byType(OverflowBar)).width, 152); // 152 = 48 + 4 + 64 + 4 + 32

    await tester.pumpWidget(buildFrame(width: 150));
    expect(tester.getSize(find.byType(OverflowBar)).width, 150);
  });

  testWidgets('OverflowBar intrinsic height', (WidgetTester tester) async {
    Widget buildFrame({ required double maxWidth }) {
      return Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Container(
            width: maxWidth,
            alignment: Alignment.topLeft,
            child: IntrinsicHeight(
              child: OverflowBar(
                spacing: 4,
                overflowSpacing: 8,
                children: const <Widget>[
                  SizedBox(width: 48, height: 50),
                  SizedBox(width: 64, height: 25),
                  SizedBox(width: 32, height: 75),
                ],
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame(maxWidth: 800));
    expect(tester.getSize(find.byType(OverflowBar)).height, 75); // 75 = max(50, 25, 75)

    await tester.pumpWidget(buildFrame(maxWidth: 150));
    expect(tester.getSize(find.byType(OverflowBar)).height, 166); // 166 = 50 + 8 + 25 + 8 + 75
  });


  testWidgets('OverflowBar is wider that its intrinsic width', (WidgetTester tester) async {
    final Key key0 = UniqueKey();
    final Key key1 = UniqueKey();
    final Key key2 = UniqueKey();

    Widget buildFrame(TextDirection textDirection) {
      return Directionality(
        textDirection: textDirection,
        child: SizedBox(
          width: 800,
          // intrinsic width = 50 + 10 + 60 + 10 + 70 = 200
          child: OverflowBar(
            spacing: 10,
            children: <Widget>[
              SizedBox(key: key0, width: 50, height: 50),
              SizedBox(key: key1, width: 60, height: 50),
              SizedBox(key: key2, width: 70, height: 50),
            ],
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame(TextDirection.ltr));
    expect(tester.getSize(find.byType(OverflowBar)), const Size(800.0, 600.0));
    expect(tester.getTopLeft(find.byKey(key0)).dx, 0);
    expect(tester.getTopLeft(find.byKey(key1)).dx, 60);
    expect(tester.getTopLeft(find.byKey(key2)).dx, 130);

    await tester.pumpWidget(buildFrame(TextDirection.rtl));
    expect(tester.getSize(find.byType(OverflowBar)), const Size(800.0, 600.0));
    expect(tester.getTopLeft(find.byKey(key0)).dx, 750);
    expect(tester.getTopLeft(find.byKey(key1)).dx, 680);
    expect(tester.getTopLeft(find.byKey(key2)).dx, 600);
  });

  testWidgets('OverflowBar with alignment should match Row with mainAxisAlignment', (WidgetTester tester) async {
    final Key key0 = UniqueKey();
    final Key key1 = UniqueKey();
    final Key key2 = UniqueKey();

    // This list of children appears in a Row and an OverflowBar, so each
    // find.byKey() for key0, key1, key2 returns two widgets.
    final List<Widget> children = <Widget>[
      SizedBox(key: key0, width: 50, height: 50),
      SizedBox(key: key1, width: 70, height: 50),
      SizedBox(key: key2, width: 80, height: 50),
    ];

    const List<MainAxisAlignment> allAlignments = <MainAxisAlignment>[
      MainAxisAlignment.start,
      MainAxisAlignment.center,
      MainAxisAlignment.end,
      MainAxisAlignment.spaceBetween,
      MainAxisAlignment.spaceAround,
      MainAxisAlignment.spaceEvenly,
    ];

    const List<TextDirection> allTextDirections = <TextDirection>[
      TextDirection.ltr,
      TextDirection.rtl,
    ];

    Widget buildFrame(MainAxisAlignment alignment, TextDirection textDirection) {
      return Directionality(
        textDirection: textDirection,
        child: Column(
          children: <Widget>[
            OverflowBar(
              alignment: alignment,
              children: children,
            ),
            Row(
              mainAxisAlignment: alignment,
              children: children,
            ),
          ],
        ),
      );
    }

    // Each key from key0, key1, key2 maps to one child in the OverflowBar
    // and a matching child in the Row. We expect the children to be the
    // same size and for their left and right edges to align.
    void testLayout() {
      expect(tester.getSize(find.byType(OverflowBar)), const Size(800, 50));
      for (final Key key in <Key>[key0, key1, key2]) {
        final Finder matchingChildren = find.byKey(key);
        expect(matchingChildren.evaluate().length, 2);
        final Rect rect0 = tester.getRect(matchingChildren.first);
        final Rect rect1 = tester.getRect(matchingChildren.last);
        expect(rect0.size, rect1.size);
        expect(rect0.left, rect1.left);
        expect(rect0.right, rect1.right);
      }
    }

    for (final MainAxisAlignment alignment in allAlignments) {
      for (final TextDirection textDirection in allTextDirections) {
        await tester.pumpWidget(buildFrame(alignment, textDirection));
        testLayout();
      }
    }
  });
}
