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

void main() {
  testWidgets('DrawerButton control test', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Scaffold(
          body: DrawerButton(),
          drawer: Drawer(),
        ),
      ),
    );

    await tester.pumpAndSettle();

    expect(find.byType(Drawer), findsNothing);

    await tester.tap(find.byType(DrawerButton));

    await tester.pumpAndSettle();

    expect(find.byType(Drawer), findsOneWidget);
  });

  testWidgets('DrawerButton onPressed overrides default end drawer open behaviour',
      (WidgetTester tester) async {
    bool customCallbackWasCalled = false;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Center(
            child: DrawerButton(
                onPressed: () => customCallbackWasCalled = true),
          ),
          drawer: const Drawer(),
        ),
      ),
    );

    await tester.pumpAndSettle();
    expect(find.byType(Drawer), findsNothing); // Start off with a closed drawer
    expect(customCallbackWasCalled,
        false); // customCallbackWasCalled should still be false.
    await tester.tap(find.byType(DrawerButton));

    await tester.pumpAndSettle();

    // Drawer is still closed
    expect(find.byType(Drawer), findsNothing);
    // The custom callback is called, setting customCallbackWasCalled to true.
    expect(customCallbackWasCalled, true);
  });

  testWidgets('DrawerButton icon', (WidgetTester tester) async {
    final Key androidKey = UniqueKey();
    final Key iOSKey = UniqueKey();
    final Key linuxKey = UniqueKey();
    final Key macOSKey = UniqueKey();
    final Key windowsKey = UniqueKey();

    await tester.pumpWidget(
      MaterialApp(
        home: Column(
          children: <Widget>[
            Theme(
              data: ThemeData(platform: TargetPlatform.android),
              child: DrawerButtonIcon(key: androidKey),
            ),
            Theme(
              data: ThemeData(platform: TargetPlatform.iOS),
              child: DrawerButtonIcon(key: iOSKey),
            ),
            Theme(
              data: ThemeData(platform: TargetPlatform.linux),
              child: DrawerButtonIcon(key: linuxKey),
            ),
            Theme(
              data: ThemeData(platform: TargetPlatform.macOS),
              child: DrawerButtonIcon(key: macOSKey),
            ),
            Theme(
              data: ThemeData(platform: TargetPlatform.windows),
              child: DrawerButtonIcon(key: windowsKey),
            ),
          ],
        ),
      ),
    );

    final Icon androidIcon = tester.widget(find.descendant(
        of: find.byKey(androidKey), matching: find.byType(Icon)));
    final Icon iOSIcon = tester.widget(
        find.descendant(of: find.byKey(iOSKey), matching: find.byType(Icon)));
    final Icon linuxIcon = tester.widget(
        find.descendant(of: find.byKey(linuxKey), matching: find.byType(Icon)));
    final Icon macOSIcon = tester.widget(
        find.descendant(of: find.byKey(macOSKey), matching: find.byType(Icon)));
    final Icon windowsIcon = tester.widget(find.descendant(
        of: find.byKey(windowsKey), matching: find.byType(Icon)));

    // All icons for drawer are the same
    expect(iOSIcon.icon == androidIcon.icon, isTrue);
    expect(linuxIcon.icon == androidIcon.icon, isTrue);
    expect(macOSIcon.icon == androidIcon.icon, isTrue);
    expect(windowsIcon.icon == androidIcon.icon, isTrue);
  });

  testWidgets('DrawerButton color', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: DrawerButton(
            color: Colors.red,
          ),
        ),
      ),
    );

    final RichText iconText = tester.firstWidget(find.descendant(
      of: find.byType(DrawerButton),
      matching: find.byType(RichText),
    ));
    expect(iconText.text.style!.color, Colors.red);
  });

  testWidgets('DrawerButton color with ButtonStyle', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: true),
        home: const Material(
          child: DrawerButton(
            style: ButtonStyle(
              iconColor: MaterialStatePropertyAll<Color>(Colors.red),
            ),
          ),
        ),
      ),
    );

    final RichText iconText = tester.firstWidget(find.descendant(
      of: find.byType(DrawerButton),
      matching: find.byType(RichText),
    ));
    expect(iconText.text.style!.color, Colors.red);
  });

  testWidgets('DrawerButton semantics', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: Center(
            child: DrawerButton(),
          ),
        ),
      ),
    );

    await tester.pumpAndSettle();

    final String? expectedLabel;
    switch (defaultTargetPlatform) {
      case TargetPlatform.android:
        expectedLabel = 'Open navigation menu';
      case TargetPlatform.fuchsia:
      case TargetPlatform.iOS:
      case TargetPlatform.linux:
      case TargetPlatform.macOS:
      case TargetPlatform.windows:
        expectedLabel = null;
    }
    expect(tester.getSemantics(find.byType(DrawerButton)), matchesSemantics(
      tooltip: 'Open navigation menu',
      label: expectedLabel,
      isButton: true,
      hasEnabledState: true,
      isEnabled: true,
      hasTapAction: true,
      isFocusable: true,
    ));
    handle.dispose();
  }, variant: TargetPlatformVariant.all());

  testWidgets('EndDrawerButton control test', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Scaffold(
          body: EndDrawerButton(),
          endDrawer: Drawer(),
        ),
      ),
    );

    await tester.pumpAndSettle();

    expect(find.byType(Drawer), findsNothing);

    await tester.tap(find.byType(EndDrawerButton));

    await tester.pumpAndSettle();

    expect(find.byType(Drawer), findsOneWidget);
  });

  testWidgets('EndDrawerButton semantics', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: Center(
            child: EndDrawerButton(),
          ),
        ),
      ),
    );

    await tester.pumpAndSettle();
    final String? expectedLabel;
    switch (defaultTargetPlatform) {
      case TargetPlatform.android:
        expectedLabel = 'Open navigation menu';
      case TargetPlatform.fuchsia:
      case TargetPlatform.iOS:
      case TargetPlatform.linux:
      case TargetPlatform.macOS:
      case TargetPlatform.windows:
        expectedLabel = null;
    }
    expect(tester.getSemantics(find.byType(EndDrawerButton)), matchesSemantics(
      tooltip: 'Open navigation menu',
      label: expectedLabel,
      isButton: true,
      hasEnabledState: true,
      isEnabled: true,
      hasTapAction: true,
      isFocusable: true,
    ));
    handle.dispose();
  }, variant: TargetPlatformVariant.all());

  testWidgets('EndDrawerButton color', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: EndDrawerButton(
            color: Colors.red,
          ),
        ),
      ),
    );

    final RichText iconText = tester.firstWidget(find.descendant(
      of: find.byType(EndDrawerButton),
      matching: find.byType(RichText),
    ));
    expect(iconText.text.style!.color, Colors.red);
  });

  testWidgets('EndDrawerButton color with ButtonStyle', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: true),
        home: const Material(
          child: EndDrawerButton(
            style: ButtonStyle(
              iconColor: MaterialStatePropertyAll<Color>(Colors.red),
            ),
          ),
        ),
      ),
    );

    final RichText iconText = tester.firstWidget(find.descendant(
      of: find.byType(EndDrawerButton),
      matching: find.byType(RichText),
    ));
    expect(iconText.text.style!.color, Colors.red);
  });

  testWidgets('EndDrawerButton onPressed overrides default end drawer open behaviour',
      (WidgetTester tester) async {
    bool customCallbackWasCalled = false;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Center(
            child: EndDrawerButton(onPressed: () => customCallbackWasCalled = true),
          ),
          endDrawer: const Drawer(),
        ),
      ),
    );

    await tester.pumpAndSettle();
    expect(find.byType(Drawer), findsNothing); // Start off with a closed drawer
    expect(customCallbackWasCalled,
        false); // customCallbackWasCalled should still be false.
    await tester.tap(find.byType(EndDrawerButton));

    await tester.pumpAndSettle();

    // Drawer is still closed
    expect(find.byType(Drawer), findsNothing);
    // The custom callback is called, setting customCallbackWasCalled to true.
    expect(customCallbackWasCalled, true);
  });
}
