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

void main() {
  group('SafeArea', () {
    testWidgets('SafeArea - basic', (WidgetTester tester) async {
      await tester.pumpWidget(
        const MediaQuery(
          data: MediaQueryData(padding: EdgeInsets.all(20.0)),
          child: SafeArea(
            left: false,
            child: Placeholder(),
          ),
        ),
      );
      expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(0.0, 20.0));
      expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 580.0));
    });

    testWidgets('SafeArea - with minimums', (WidgetTester tester) async {
      await tester.pumpWidget(
        const MediaQuery(
          data: MediaQueryData(padding: EdgeInsets.all(20.0)),
          child: SafeArea(
            top: false,
            minimum: EdgeInsets.fromLTRB(0.0, 10.0, 20.0, 30.0),
            child: Placeholder(),
          ),
        ),
      );
      expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(20.0, 10.0));
      expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 570.0));
    });

    testWidgets('SafeArea - nested', (WidgetTester tester) async {
      await tester.pumpWidget(
        const MediaQuery(
          data: MediaQueryData(padding: EdgeInsets.all(20.0)),
          child: SafeArea(
            top: false,
            child: SafeArea(
              right: false,
              child: Placeholder(),
            ),
          ),
        ),
      );
      expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(20.0, 20.0));
      expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 580.0));
    });

    testWidgets('SafeArea - changing', (WidgetTester tester) async {
      const Widget child = SafeArea(
        bottom: false,
        child: SafeArea(
          left: false,
          bottom: false,
          child: Placeholder(),
        ),
      );
      await tester.pumpWidget(
        const MediaQuery(
          data: MediaQueryData(padding: EdgeInsets.all(20.0)),
          child: child,
        ),
      );
      expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(20.0, 20.0));
      expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(780.0, 600.0));
      await tester.pumpWidget(
        const MediaQuery(
          data: MediaQueryData(padding: EdgeInsets.only(
            left: 100.0,
            top: 30.0,
            bottom: 40.0,
          )),
          child: child,
        ),
      );
      expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(100.0, 30.0));
      expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
    });

    testWidgets('SafeArea - properties', (WidgetTester tester) async {
      final SafeArea child = SafeArea(
        right: false,
        bottom: false,
        child: Container(),
      );
      final DiagnosticPropertiesBuilder properties = DiagnosticPropertiesBuilder();
      child.debugFillProperties(properties);

      expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid left padding'), true);
      expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid right padding'), false);
      expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid top padding'), true);
      expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid bottom padding'), false);
    });

    group('SafeArea maintains bottom viewPadding when specified for consumed bottom padding', () {
      Widget boilerplate(Widget child) {
        return Localizations(
          locale: const Locale('en', 'us'),
          delegates: const <LocalizationsDelegate<dynamic>>[
            DefaultWidgetsLocalizations.delegate,
            DefaultMaterialLocalizations.delegate,
          ],
          child: Directionality(textDirection: TextDirection.ltr, child: child),
        );
      }

      testWidgets('SafeArea alone.', (WidgetTester tester) async {
        final Widget child = boilerplate(SafeArea(
          maintainBottomViewPadding: true,
          child: Column(
            children: const <Widget>[
              Expanded(child: Placeholder()),
            ],
          ),
        ));

        await tester.pumpWidget(
          MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.symmetric(vertical: 20.0),
              viewPadding: EdgeInsets.only(bottom: 20.0),
            ),
            child: child,
          ),
        );
        final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
        // Consume bottom padding - as if by the keyboard opening
        await tester.pumpWidget(
          MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.only(top: 20.0),
              viewPadding: EdgeInsets.only(bottom: 20.0),
              viewInsets: EdgeInsets.only(bottom: 300.0),
            ),
            child: child,
          ),
        );
        final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
        expect(initialPoint, finalPoint);
      });

      testWidgets('SafeArea alone - partial ViewInsets consume Padding', (WidgetTester tester) async {
        final Widget child = boilerplate(SafeArea(
          maintainBottomViewPadding: true,
          child: Column(
            children: const <Widget>[
              Expanded(child: Placeholder()),
            ],
          ),
        ));

        await tester.pumpWidget(
          MediaQuery(
            data: const MediaQueryData(
              viewPadding: EdgeInsets.only(bottom: 20.0),
            ),
            child: child,
          ),
        );
        final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
        // Consume bottom padding - as if by the keyboard opening
        await tester.pumpWidget(
          MediaQuery(
            data: const MediaQueryData(
              viewPadding: EdgeInsets.only(bottom: 20.0),
              viewInsets: EdgeInsets.only(bottom: 10.0),
            ),
            child: child,
          ),
        );
        final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
        expect(initialPoint, finalPoint);
      });

      testWidgets('SafeArea with nested Scaffold', (WidgetTester tester) async {
        final Widget child = boilerplate(SafeArea(
          maintainBottomViewPadding: true,
          child: Scaffold(
            resizeToAvoidBottomInset: false,
            body: Column(
              children: const <Widget>[
                Expanded(child: Placeholder()),
              ],
            ),
          ),
        ));

        await tester.pumpWidget(
          MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.symmetric(vertical: 20.0),
              viewPadding: EdgeInsets.only(bottom: 20.0),
            ),
            child: child,
          ),
        );
        final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
        // Consume bottom padding - as if by the keyboard opening
        await tester.pumpWidget(
          MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.only(top: 20.0),
              viewPadding: EdgeInsets.only(bottom: 20.0),
              viewInsets: EdgeInsets.only(bottom: 300.0),
            ),
            child: child,
          ),
        );
        final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
        expect(initialPoint, finalPoint);
      });

      testWidgets('SafeArea with nested Scaffold  - partial ViewInsets consume Padding', (WidgetTester tester) async {
        final Widget child = boilerplate(SafeArea(
          maintainBottomViewPadding: true,
          child: Scaffold(
            resizeToAvoidBottomInset: false,
            body: Column(
              children: const <Widget>[
                Expanded(child: Placeholder()),
              ],
            ),
          ),
        ));

        await tester.pumpWidget(
          MediaQuery(
            data: const MediaQueryData(
              viewPadding: EdgeInsets.only(bottom: 20.0),
            ),
            child: child,
          ),
        );
        final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
        // Consume bottom padding - as if by the keyboard opening
        await tester.pumpWidget(
          MediaQuery(
            data: const MediaQueryData(
              viewPadding: EdgeInsets.only(bottom: 20.0),
              viewInsets: EdgeInsets.only(bottom: 10.0),
            ),
            child: child,
          ),
        );
        final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
        expect(initialPoint, finalPoint);
      });
    });
  });

  group('SliverSafeArea', () {
    Widget buildWidget(EdgeInsets mediaPadding, Widget sliver) {
      return MediaQuery(
        data: MediaQueryData(padding: mediaPadding),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Viewport(
            offset: ViewportOffset.fixed(0.0),
            slivers: <Widget>[
              const SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('before'))),
              sliver,
              const SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('after'))),
            ],
          ),
        ),
      );
    }

    void verify(WidgetTester tester, List<Rect> expectedRects) {
      final List<Rect> testAnswers = tester.renderObjectList<RenderBox>(find.byType(SizedBox)).map<Rect>(
        (RenderBox target) {
          final Offset topLeft = target.localToGlobal(Offset.zero);
          final Offset bottomRight = target.localToGlobal(target.size.bottomRight(Offset.zero));
          return Rect.fromPoints(topLeft, bottomRight);
        },
      ).toList();
      expect(testAnswers, equals(expectedRects));
    }

    testWidgets('SliverSafeArea - basic', (WidgetTester tester) async {
      await tester.pumpWidget(
        buildWidget(
          const EdgeInsets.all(20.0),
          const SliverSafeArea(
            left: false,
            sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
          ),
        ),
      );
      verify(tester, <Rect>[
        const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
        const Rect.fromLTWH(0.0, 120.0, 780.0, 100.0),
        const Rect.fromLTWH(0.0, 240.0, 800.0, 100.0),
      ]);
    });

    testWidgets('SliverSafeArea - basic', (WidgetTester tester) async {
      await tester.pumpWidget(
        buildWidget(
          const EdgeInsets.all(20.0),
          const SliverSafeArea(
            top: false,
            minimum: EdgeInsets.fromLTRB(0.0, 10.0, 20.0, 30.0),
            sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
          ),
        ),
      );
      verify(tester, <Rect>[
        const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
        const Rect.fromLTWH(20.0, 110.0, 760.0, 100.0),
        const Rect.fromLTWH(0.0, 240.0, 800.0, 100.0),
      ]);
    });

    testWidgets('SliverSafeArea - nested', (WidgetTester tester) async {
      await tester.pumpWidget(
        buildWidget(
          const EdgeInsets.all(20.0),
          const SliverSafeArea(
            top: false,
            sliver: SliverSafeArea(
              right: false,
              sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
            ),
          ),
        ),
      );
      verify(tester, <Rect>[
        const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
        const Rect.fromLTWH(20.0, 120.0, 760.0, 100.0),
        const Rect.fromLTWH(0.0, 240.0, 800.0, 100.0),
      ]);
    });

    testWidgets('SliverSafeArea - changing', (WidgetTester tester) async {
      const Widget sliver = SliverSafeArea(
        bottom: false,
        sliver: SliverSafeArea(
          left: false,
          bottom: false,
          sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
        ),
      );
      await tester.pumpWidget(
        buildWidget(
          const EdgeInsets.all(20.0),
          sliver,
        ),
      );
      verify(tester, <Rect>[
        const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
        const Rect.fromLTWH(20.0, 120.0, 760.0, 100.0),
        const Rect.fromLTWH(0.0, 220.0, 800.0, 100.0),
      ]);

      await tester.pumpWidget(
        buildWidget(
          const EdgeInsets.only(
            left: 100.0,
            top: 30.0,
            bottom: 40.0,
          ),
          sliver,
        ),
      );
      verify(tester, <Rect>[
        const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0),
        const Rect.fromLTWH(100.0, 130.0, 700.0, 100.0),
        const Rect.fromLTWH(0.0, 230.0, 800.0, 100.0),
      ]);
    });
  });

  testWidgets('SliverSafeArea - properties', (WidgetTester tester) async {
    const SliverSafeArea child = SliverSafeArea(
      right: false,
      bottom: false,
      sliver: SliverToBoxAdapter(child: SizedBox(width: 800.0, height: 100.0, child: Text('padded'))),
    );
    final DiagnosticPropertiesBuilder properties = DiagnosticPropertiesBuilder();
    child.debugFillProperties(properties);

    expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid left padding'), true);
    expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid right padding'), false);
    expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid top padding'), true);
    expect(properties.properties.any((DiagnosticsNode n) => n is FlagProperty && n.toString() == 'avoid bottom padding'), false);
  });
}
