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


void main() {
  test('BottomNavigationBarThemeData copyWith, ==, hashCode basics', () {
    expect(const BottomNavigationBarThemeData(), const BottomNavigationBarThemeData().copyWith());
    expect(const BottomNavigationBarThemeData().hashCode, const BottomNavigationBarThemeData().copyWith().hashCode);
  });

  test('BottomNavigationBarThemeData defaults', () {
    const BottomNavigationBarThemeData themeData = BottomNavigationBarThemeData();
    expect(themeData.backgroundColor, null);
    expect(themeData.elevation, null);
    expect(themeData.selectedIconTheme, null);
    expect(themeData.unselectedIconTheme, null);
    expect(themeData.selectedItemColor, null);
    expect(themeData.unselectedItemColor, null);
    expect(themeData.selectedLabelStyle, null);
    expect(themeData.unselectedLabelStyle, null);
    expect(themeData.showSelectedLabels, null);
    expect(themeData.showUnselectedLabels, null);
    expect(themeData.type, null);
    expect(themeData.landscapeLayout, null);
    expect(themeData.mouseCursor, null);

    const BottomNavigationBarTheme theme = BottomNavigationBarTheme(data: BottomNavigationBarThemeData(), child: SizedBox());
    expect(theme.data.backgroundColor, null);
    expect(theme.data.elevation, null);
    expect(theme.data.selectedIconTheme, null);
    expect(theme.data.unselectedIconTheme, null);
    expect(theme.data.selectedItemColor, null);
    expect(theme.data.unselectedItemColor, null);
    expect(theme.data.selectedLabelStyle, null);
    expect(theme.data.unselectedLabelStyle, null);
    expect(theme.data.showSelectedLabels, null);
    expect(theme.data.showUnselectedLabels, null);
    expect(theme.data.type, null);
    expect(themeData.landscapeLayout, null);
    expect(themeData.mouseCursor, null);
  });

  testWidgets('Default BottomNavigationBarThemeData debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const BottomNavigationBarThemeData().debugFillProperties(builder);

    final List<String> description = builder.properties
        .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
        .map((DiagnosticsNode node) => node.toString())
        .toList();

    expect(description, <String>[]);
  });

  testWidgets('BottomNavigationBarThemeData implements debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const BottomNavigationBarThemeData(
      backgroundColor: Color(0xfffffff0),
      elevation: 10.0,
      selectedIconTheme: IconThemeData(size: 1.0),
      unselectedIconTheme: IconThemeData(size: 2.0),
      selectedItemColor: Color(0xfffffff1),
      unselectedItemColor: Color(0xfffffff2),
      selectedLabelStyle: TextStyle(fontSize: 3.0),
      unselectedLabelStyle: TextStyle(fontSize: 4.0),
      showSelectedLabels: true,
      showUnselectedLabels: true,
      type: BottomNavigationBarType.fixed,
      mouseCursor: MaterialStateMouseCursor.clickable,
    ).debugFillProperties(builder);

    final List<String> description = builder.properties
        .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
        .map((DiagnosticsNode node) => node.toString())
        .toList();

    expect(description[0], 'backgroundColor: Color(0xfffffff0)');
    expect(description[1], 'elevation: 10.0');

    // Ignore instance address for IconThemeData.
    expect(description[2].contains('selectedIconTheme: IconThemeData'), isTrue);
    expect(description[2].contains('(size: 1.0)'), isTrue);
    expect(description[3].contains('unselectedIconTheme: IconThemeData'), isTrue);
    expect(description[3].contains('(size: 2.0)'), isTrue);

    expect(description[4], 'selectedItemColor: Color(0xfffffff1)');
    expect(description[5], 'unselectedItemColor: Color(0xfffffff2)');
    expect(description[6], 'selectedLabelStyle: TextStyle(inherit: true, size: 3.0)');
    expect(description[7], 'unselectedLabelStyle: TextStyle(inherit: true, size: 4.0)');
    expect(description[8], 'showSelectedLabels: true');
    expect(description[9], 'showUnselectedLabels: true');
    expect(description[10], 'type: BottomNavigationBarType.fixed');
    expect(description[11], 'mouseCursor: MaterialStateMouseCursor(clickable)');
  });

  testWidgets('BottomNavigationBar is themeable', (WidgetTester tester) async {
    const Color backgroundColor = Color(0xFF000001);
    const Color selectedItemColor = Color(0xFF000002);
    const Color unselectedItemColor = Color(0xFF000003);
    const IconThemeData selectedIconTheme = IconThemeData(size: 10);
    const IconThemeData unselectedIconTheme = IconThemeData(size: 11);
    const TextStyle selectedTextStyle = TextStyle(fontSize: 22);
    const TextStyle unselectedTextStyle = TextStyle(fontSize: 21);
    const double elevation = 9.0;

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          bottomNavigationBarTheme: BottomNavigationBarThemeData(
            backgroundColor: backgroundColor,
            selectedItemColor: selectedItemColor,
            unselectedItemColor: unselectedItemColor,
            selectedIconTheme: selectedIconTheme,
            unselectedIconTheme: unselectedIconTheme,
            elevation: elevation,
            showUnselectedLabels: true,
            showSelectedLabels: true,
            type: BottomNavigationBarType.fixed,
            selectedLabelStyle: selectedTextStyle,
            unselectedLabelStyle: unselectedTextStyle,
            mouseCursor: MaterialStateProperty.resolveWith<MouseCursor?>((Set<MaterialState> states) {
              if (states.contains(MaterialState.selected)) {
                return SystemMouseCursors.grab;
              }
              return SystemMouseCursors.move;
            }),
          ),
        ),
        home: Scaffold(
          bottomNavigationBar: BottomNavigationBar(
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.ac_unit),
                label: 'AC',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.access_alarm),
                label: 'Alarm',
              ),
            ],
          ),
        ),
      ),
    );

    final Finder findACTransform = find.descendant(
      of: find.byType(BottomNavigationBar),
      matching: find.ancestor(
        of: find.text('AC'),
        matching: find.byType(Transform),
      ),
    );
    final Finder findAlarmTransform = find.descendant(
      of: find.byType(BottomNavigationBar),
      matching: find.ancestor(
        of: find.text('Alarm'),
        matching: find.byType(Transform),
      ),
    );
    final TextStyle selectedFontStyle = tester.renderObject<RenderParagraph>(find.text('AC')).text.style!;
    final TextStyle selectedIcon = _iconStyle(tester, Icons.ac_unit);
    final TextStyle unselectedIcon = _iconStyle(tester, Icons.access_alarm);
    expect(selectedFontStyle.fontSize, selectedFontStyle.fontSize);
    // Unselected label has a font size of 22 but is scaled down to be font size 21.
    expect(
      tester.firstWidget<Transform>(findAlarmTransform).transform,
      equals(Matrix4.diagonal3(Vector3.all(unselectedTextStyle.fontSize! / selectedTextStyle.fontSize!))),
    );
    expect(selectedIcon.color, equals(selectedItemColor));
    expect(selectedIcon.fontSize, equals(selectedIconTheme.size));
    expect(unselectedIcon.color, equals(unselectedItemColor));
    expect(unselectedIcon.fontSize, equals(unselectedIconTheme.size));
    // There should not be any [Opacity] or [FadeTransition] widgets
    // since showUnselectedLabels and showSelectedLabels are true.
    final Finder findOpacity = find.descendant(
      of: find.byType(BottomNavigationBar),
      matching: find.byType(Opacity),
    );
    final Finder findFadeTransition = find.descendant(
      of: find.byType(BottomNavigationBar),
      matching: find.byType(FadeTransition),
    );
    expect(findOpacity, findsNothing);
    expect(findFadeTransition, findsNothing);
    expect(_material(tester).elevation, equals(elevation));
    expect(_material(tester).color, equals(backgroundColor));

    final Offset selectedBarItem = tester.getCenter(findACTransform);
    final Offset unselectedBarItem = tester.getCenter(findAlarmTransform);
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    await gesture.moveTo(selectedBarItem);
    await tester.pumpAndSettle();
    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab);
    await gesture.moveTo(unselectedBarItem);
    await tester.pumpAndSettle();
    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.move);
  });

  testWidgets('BottomNavigationBar properties are taken over the theme values', (WidgetTester tester) async {
    const Color themeBackgroundColor = Color(0xFF000001);
    const Color themeSelectedItemColor = Color(0xFF000002);
    const Color themeUnselectedItemColor = Color(0xFF000003);
    const IconThemeData themeSelectedIconTheme = IconThemeData(size: 10);
    const IconThemeData themeUnselectedIconTheme = IconThemeData(size: 11);
    const TextStyle themeSelectedTextStyle = TextStyle(fontSize: 22);
    const TextStyle themeUnselectedTextStyle = TextStyle(fontSize: 21);
    const double themeElevation = 9.0;
    const BottomNavigationBarLandscapeLayout themeLandscapeLayout = BottomNavigationBarLandscapeLayout.centered;
    const MaterialStateMouseCursor themeCursor = MaterialStateMouseCursor.clickable;

    const Color backgroundColor = Color(0xFF000004);
    const Color selectedItemColor = Color(0xFF000005);
    const Color unselectedItemColor = Color(0xFF000006);
    const IconThemeData selectedIconTheme = IconThemeData(size: 15);
    const IconThemeData unselectedIconTheme = IconThemeData(size: 16);
    const TextStyle selectedTextStyle = TextStyle(fontSize: 25);
    const TextStyle unselectedTextStyle = TextStyle(fontSize: 26);
    const double elevation = 7.0;
    const BottomNavigationBarLandscapeLayout landscapeLayout = BottomNavigationBarLandscapeLayout.spread;
    const MaterialStateMouseCursor cursor = MaterialStateMouseCursor.textable;

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          bottomNavigationBarTheme: const BottomNavigationBarThemeData(
            backgroundColor: themeBackgroundColor,
            selectedItemColor: themeSelectedItemColor,
            unselectedItemColor: themeUnselectedItemColor,
            selectedIconTheme: themeSelectedIconTheme,
            unselectedIconTheme: themeUnselectedIconTheme,
            elevation: themeElevation,
            showUnselectedLabels: false,
            showSelectedLabels: false,
            type: BottomNavigationBarType.shifting,
            selectedLabelStyle: themeSelectedTextStyle,
            unselectedLabelStyle: themeUnselectedTextStyle,
            landscapeLayout: themeLandscapeLayout,
            mouseCursor: themeCursor,
          ),
        ),
        home: Scaffold(
          bottomNavigationBar: BottomNavigationBar(
            backgroundColor: backgroundColor,
            selectedItemColor: selectedItemColor,
            unselectedItemColor: unselectedItemColor,
            selectedIconTheme: selectedIconTheme,
            unselectedIconTheme: unselectedIconTheme,
            elevation: elevation,
            showUnselectedLabels: true,
            showSelectedLabels: true,
            type: BottomNavigationBarType.fixed,
            selectedLabelStyle: selectedTextStyle,
            unselectedLabelStyle: unselectedTextStyle,
            landscapeLayout: landscapeLayout,
            mouseCursor: cursor,
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.ac_unit),
                label: 'AC',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.access_alarm),
                label: 'Alarm',
              ),
            ],
          ),
        ),
      ),
    );

    Finder findDescendantOfBottomNavigationBar(Finder finder) {
      return find.descendant(
        of: find.byType(BottomNavigationBar),
        matching: finder,
      );
    }

    final TextStyle selectedFontStyle = tester.renderObject<RenderParagraph>(find.text('AC')).text.style!;
    final TextStyle selectedIcon = _iconStyle(tester, Icons.ac_unit);
    final TextStyle unselectedIcon = _iconStyle(tester, Icons.access_alarm);
    expect(selectedFontStyle.fontSize, selectedFontStyle.fontSize);
    // Unselected label has a font size of 22 but is scaled down to be font size 21.
    expect(
      tester.firstWidget<Transform>(
        findDescendantOfBottomNavigationBar(
          find.ancestor(
            of: find.text('Alarm'),
            matching: find.byType(Transform),
          ),
        ),
      ).transform,
      equals(Matrix4.diagonal3(Vector3.all(unselectedTextStyle.fontSize! / selectedTextStyle.fontSize!))),
    );
    expect(selectedIcon.color, equals(selectedItemColor));
    expect(selectedIcon.fontSize, equals(selectedIconTheme.size));
    expect(unselectedIcon.color, equals(unselectedItemColor));
    expect(unselectedIcon.fontSize, equals(unselectedIconTheme.size));
    // There should not be any [Opacity] or [FadeTransition] widgets
    // since showUnselectedLabels and showSelectedLabels are true.
    final Finder findOpacity = findDescendantOfBottomNavigationBar(
      find.byType(Opacity),
    );
    final Finder findFadeTransition = findDescendantOfBottomNavigationBar(
      find.byType(FadeTransition),
    );
    expect(findOpacity, findsNothing);
    expect(findFadeTransition, findsNothing);
    expect(_material(tester).elevation, equals(elevation));
    expect(_material(tester).color, equals(backgroundColor));

    final Offset barItem = tester.getCenter(
      findDescendantOfBottomNavigationBar(
        find.ancestor(
          of: find.text('AC'),
          matching: find.byType(Transform),
        ),
      ),
    );
    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer();
    await gesture.moveTo(barItem);
    await tester.pumpAndSettle();
    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
  });

  testWidgets('BottomNavigationBarTheme can be used to hide all labels', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/66738.
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          bottomNavigationBarTheme: const BottomNavigationBarThemeData(
            showSelectedLabels: false,
            showUnselectedLabels: false,
          ),
        ),
        home: Scaffold(
          bottomNavigationBar: BottomNavigationBar(
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.ac_unit),
                label: 'AC',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.access_alarm),
                label: 'Alarm',
              ),
            ],
          ),
        ),
      ),
    );


    final Finder findVisibility = find.descendant(
      of: find.byType(BottomNavigationBar),
      matching: find.byType(Visibility),
    );

    expect(findVisibility, findsNWidgets(2));
    expect(tester.widget<Visibility>(findVisibility.at(0)).visible, false);
    expect(tester.widget<Visibility>(findVisibility.at(1)).visible, false);
  });

  testWidgets('BottomNavigationBarTheme can be used to hide selected labels', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/66738.
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          bottomNavigationBarTheme: const BottomNavigationBarThemeData(
            showSelectedLabels: false,
            showUnselectedLabels: true,
          ),
        ),
        home: Scaffold(
          bottomNavigationBar: BottomNavigationBar(
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.ac_unit),
                label: 'AC',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.access_alarm),
                label: 'Alarm',
              ),
            ],
          ),
        ),
      ),
    );


    final Finder findFadeTransition = find.descendant(
      of: find.byType(BottomNavigationBar),
      matching: find.byType(FadeTransition),
    );

    expect(findFadeTransition, findsNWidgets(2));
    expect(tester.widget<FadeTransition>(findFadeTransition.at(0)).opacity.value, 0.0);
    expect(tester.widget<FadeTransition>(findFadeTransition.at(1)).opacity.value, 1.0);
  });

  testWidgets('BottomNavigationBarTheme can be used to hide unselected labels', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          bottomNavigationBarTheme: const BottomNavigationBarThemeData(
            showSelectedLabels: true,
            showUnselectedLabels: false,
          ),
        ),
        home: Scaffold(
          bottomNavigationBar: BottomNavigationBar(
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.ac_unit),
                label: 'AC',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.access_alarm),
                label: 'Alarm',
              ),
            ],
          ),
        ),
      ),
    );


    final Finder findFadeTransition = find.descendant(
      of: find.byType(BottomNavigationBar),
      matching: find.byType(FadeTransition),
    );

    expect(findFadeTransition, findsNWidgets(2));
    expect(tester.widget<FadeTransition>(findFadeTransition.at(0)).opacity.value, 1.0);
    expect(tester.widget<FadeTransition>(findFadeTransition.at(1)).opacity.value, 0.0);
  });
}

TextStyle _iconStyle(WidgetTester tester, IconData icon) {
  final RichText iconRichText = tester.widget<RichText>(
    find.descendant(of: find.byIcon(icon), matching: find.byType(RichText)),
  );
  return iconRichText.text.style!;
}

Material _material(WidgetTester tester) {
  return tester.firstWidget<Material>(
    find.descendant(of: find.byType(BottomNavigationBar), matching: find.byType(Material)),
  );
}
