import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/material.dart';

import '../../../../shared/controllers/theme_controller.dart';
import '../../../../shared/model/adaptive_response.dart';
import '../../../../shared/utils/link_text_span.dart';
import '../../../../shared/widgets/universal/list_tile_reveal.dart';
import '../../../../shared/widgets/universal/responsive_two_widgets.dart';
import '../../../../shared/widgets/universal/showcase_material.dart';
import '../../../../shared/widgets/universal/slider_list_tile_reveal.dart';
import '../../../../shared/widgets/universal/switch_list_tile_reveal.dart';
import '../../../theme/theme_values.dart';
import '../../dialogs/set_text_field_to_defaults_dialog.dart';
import '../../dialogs/set_text_field_to_dense_dialog.dart';
import '../../dialogs/set_text_field_to_m3_dialog.dart';
import '../../dialogs/set_text_field_to_outlined_dialog.dart';
import '../../shared/color_scheme_popup_menu.dart';
import '../../shared/enum_popup_menu.dart';
import '../../shared/test_adaptive_response.dart';

class TextFieldPanel extends StatelessWidget {
  const TextFieldPanel(this.controller, {super.key});
  final ThemeController controller;

  static final Uri _fcsFlutterHandleLimit = Uri(
    scheme: 'https',
    host: 'api.flutter.dev',
    path: 'flutter/material/TextSelectionThemeData/selectionHandleColor.html',
  );

  Future<void> _handleSetToM3(BuildContext context) async {
    final bool? reset = await showDialog<bool?>(
      context: context,
      builder: (BuildContext context) {
        return const SetTextFieldToM3Dialog();
      },
    );
    if (reset ?? false) {
      await controller.setTextFieldToM3();
    }
  }

  Future<void> _handleSetToDefaults(BuildContext context) async {
    final bool? reset = await showDialog<bool?>(
      context: context,
      builder: (BuildContext context) {
        return const SetTextFieldToDefaultsDialog();
      },
    );
    if (reset ?? false) {
      await controller.setTextFieldToDefaults();
    }
  }

  Future<void> _handleSetToOutlined(BuildContext context) async {
    final bool? reset = await showDialog<bool?>(
      context: context,
      builder: (BuildContext context) {
        return const SetTextFieldToOutlinedDialog();
      },
    );
    if (reset ?? false) {
      await controller.setTextFieldToPlaygroundOutlined();
    }
  }

  Future<void> _handleSetToDense(BuildContext context) async {
    final bool? reset = await showDialog<bool?>(
      context: context,
      builder: (BuildContext context) {
        return const SetTextFieldToDenseDialog();
      },
    );
    if (reset ?? false) {
      await controller.setTextFieldToPlaygroundDense();
    }
  }

  // Complex logic for the adaptive InputDecorator radius label.
  static String? _adaptiveDecoratorModeLabel(ThemeController controller) {
    if (!controller.useSubThemes && !controller.useFlexColorScheme) return null;
    final bool useAdaptiveRadius =
        controller.adaptiveResponseRadius != AdaptiveResponse.off &&
            controller.adaptiveResponseRadius != null &&
            controller.inputDecoratorBorderRadius == null;
    if (useAdaptiveRadius) {
      return 'Global (${controller.adaptiveResponseRadius?.label ?? ''})';
    }
    return null;
  }

  // Complex logic for the adaptive decorator radius label.
  static String _adaptiveDecoratorRadiusLabel(ThemeController controller) {
    final bool useFCS =
        controller.useSubThemes && controller.useFlexColorScheme;
    if (!useFCS) {
      return '4 dp';
    }
    final bool useAdaptiveInputDecoratorRadius =
        controller.adaptiveResponseInputDecoratorRadius !=
                AdaptiveResponse.off &&
            controller.adaptiveResponseInputDecoratorRadius != null;
    if (useAdaptiveInputDecoratorRadius) {
      return controller.inputDecoratorBorderRadiusAdaptive != null
          ? controller.inputDecoratorBorderRadiusAdaptive!.toStringAsFixed(0)
          : '4 dp';
    }
    final bool useAdaptiveRadius =
        controller.adaptiveResponseRadius != AdaptiveResponse.off &&
            controller.adaptiveResponseRadius != null &&
            controller.inputDecoratorBorderRadius == null;
    if (useAdaptiveRadius) {
      return controller.defaultRadiusAdaptive != null
          ? 'global ${controller.defaultRadiusAdaptive!.toStringAsFixed(0)} dp'
          : '4 dp';
    }
    return 'OFF';
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    final bool useMaterial3 = theme.useMaterial3;
    final bool isLight = theme.brightness == Brightness.light;
    final TextStyle spanTextStyle = theme.textTheme.bodySmall!
        .copyWith(color: theme.colorScheme.onSurfaceVariant);
    final TextStyle linkStyle = theme.textTheme.bodySmall!.copyWith(
      color: theme.colorScheme.primary,
      fontWeight: FontWeight.bold,
    );
    // The most common logic for enabling Playground controls.
    final bool enableControl =
        controller.useSubThemes && controller.useFlexColorScheme;
    final String unfocusedBorderDefaultLabel =
        controller.inputDecoratorBorderWidth == null &&
                controller.thinBorderWidth == null
            ? '1 dp'
            : controller.inputDecoratorBorderWidth == null &&
                    controller.thinBorderWidth != null
                ? 'global ${controller.thinBorderWidth!.toStringAsFixed(1)} dp'
                : '';
    final String focusedBorderDefaultLabel =
        controller.inputDecoratorFocusedBorderWidth == null &&
                controller.thickBorderWidth == null
            ? '2 dp'
            : controller.inputDecoratorFocusedBorderWidth == null &&
                    controller.thickBorderWidth != null
                ? 'global ${controller.thickBorderWidth!.toStringAsFixed(1)} dp'
                : '';

    // Get effective platform default global radius.
    final double? effectiveRadius = ThemeValues.effectiveRadius(controller);
    final String decoratorRadiusDefaultLabel =
        controller.inputDecoratorBorderRadius == null && effectiveRadius == null
            ? useMaterial3
                ? '4 dp'
                : '10 dp'
            : controller.inputDecoratorBorderRadius == null &&
                    effectiveRadius != null
                ? 'global ${effectiveRadius.toStringAsFixed(0)} dp'
                : '';

    // Default decorator alpha values and labels
    final double defaultBackgroundAlpha = useMaterial3
        ? 0xFF // #FF = 255 = 100% Light M3 default
        : isLight
            ? 0x0D // #0D = 13 = 5.1% Light FCS own M2 default
            : 0x14; // #14 = 20 = 7.84% Dark FCS own M2 default

    final String lightBackgroundLabel =
        enableControl && controller.inputDecoratorBackgroundAlphaLight != null
            ? '${controller.inputDecoratorBackgroundAlphaLight}'
            : '${defaultBackgroundAlpha.toInt()}';

    final String lightBackgroundLabelOpacity =
        enableControl && controller.inputDecoratorBackgroundAlphaLight != null
            ? (controller.inputDecoratorBackgroundAlphaLight! / 255 * 100)
                .toStringAsFixed(1)
            : (defaultBackgroundAlpha / 255 * 100).toStringAsFixed(1);

    final String darkBackgroundLabel =
        enableControl && controller.inputDecoratorBackgroundAlphaDark != null
            ? '${controller.inputDecoratorBackgroundAlphaDark}'
            : useMaterial3
                ? '255' // #FF = 255 = 100% Dark M3 default
                : '20'; // #14 = 20 = 7.84% Dark FCS own M2 default

    final String darkBackgroundLabelOpacity =
        enableControl && controller.inputDecoratorBackgroundAlphaDark != null
            ? (controller.inputDecoratorBackgroundAlphaDark! / 255 * 100)
                .toStringAsFixed(1)
            : (defaultBackgroundAlpha / 255 * 100).toStringAsFixed(1);

    // Defaults for tex selection setup and info.
    //
    final double defaultSelectionOpacity = isLight
        ? 0.3 // Light FCS own default
        : 0.5; // Dark FCS own default

    final String selectionLabelDefaultOpacity =
        '${(defaultSelectionOpacity * 100).toStringAsFixed(0)} %';
    //
    final String baseDefaultLabelLightColor =
        controller.inputDecoratorSchemeColorLight != null
            ? SchemeColor
                .values[controller.inputDecoratorSchemeColorLight!.index].name
            : 'primary';
    final String baseDefaultLabelDarkColor =
        controller.inputDecoratorSchemeColorDark != null
            ? SchemeColor
                .values[controller.inputDecoratorSchemeColorDark!.index].name
            : 'primary';
    //
    final String baseDefaultHandleLabelLightColor =
        controller.inputDecoratorSchemeColorLight != null &&
                controller.inputDecoratorSchemeColorLight != SchemeColor.primary
            ? SchemeColor
                .values[controller.inputDecoratorSchemeColorLight!.index].name
            : 'primary';
    final String baseDefaultHandleLabelDarkColor =
        controller.inputDecoratorSchemeColorDark != null &&
                controller.inputDecoratorSchemeColorDark != SchemeColor.primary
            ? SchemeColor
                .values[controller.inputDecoratorSchemeColorDark!.index].name
            : 'primary';

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        const SizedBox(height: 8),
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            firstWidget: ListTileReveal(
              contentPadding: ThemeValues.tilePaddingStart(context, isRow),
              title: const Text('Material-3 defaults'),
              subtitleReveal:
                  const Text('Update settings to match Material-3 default '
                      'style. Also sets text selection style.\n'
                      'Can also be used in Material-2 mode, but the result is '
                      'different from when used in actual M3 mode.'),
              trailing: IconButton(
                isSelected: true,
                onPressed: () async {
                  await _handleSetToM3(context);
                },
                icon: const Icon(Icons.refresh),
              ),
              onTap: () async {
                await _handleSetToM3(context);
              },
            ),
            lastWidget: ListTileReveal(
              contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
              title: const Text('Playground defaults'),
              subtitleReveal: const Text("Update settings to Playground's own "
                  'default values. Also resets text selection '
                  'style.\n'
                  'The defaults for Material-2 and Material-3 are slightly '
                  'different, the Material-3 mode defaults are very close '
                  'to Material defaults, but use a filled outline style.'),
              trailing: IconButton(
                isSelected: true,
                onPressed: () async {
                  await _handleSetToDefaults(context);
                },
                icon: const Icon(Icons.refresh),
              ),
              onTap: () async {
                await _handleSetToDefaults(context);
              },
            ),
            isRow: isRow,
          );
        }),
        ResponsiveTwoWidgets(
          builder: (BuildContext context, bool isRow) {
            return RowOrColumn(
              firstWidget: ListTileReveal(
                contentPadding: ThemeValues.tilePaddingStart(context, isRow),
                title: const Text('Colored outline'),
                subtitleReveal: const Text(
                  'Update settings to an example with colored '
                  'outlined border and primary opacity background '
                  'color. Also use custom colors on prefix and suffix '
                  'icons, and less padding. Used colors and opacities '
                  'varies between light and dark mode.',
                ),
                trailing: IconButton(
                  isSelected: true,
                  onPressed: () async {
                    await _handleSetToOutlined(context);
                  },
                  icon: const Icon(Icons.refresh),
                ),
                onTap: () async {
                  await _handleSetToOutlined(context);
                },
              ),
              lastWidget: ListTileReveal(
                contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                title: const Text('Dense, no focused border'),
                subtitleReveal: const Text(
                  'Update settings to an example with dense field, no '
                  'focused border and '
                  'a colored outlined border and primary opacity background '
                  'color. Also use custom colors on prefix and suffix '
                  'icons. Used colors and opacities '
                  'varies between light and dark mode.',
                ),
                trailing: IconButton(
                  isSelected: true,
                  onPressed: () async {
                    await _handleSetToDense(context);
                  },
                  icon: const Icon(Icons.refresh),
                ),
                onTap: () async {
                  await _handleSetToDense(context);
                },
              ),
              isRow: isRow,
            );
          },
        ),
        const Divider(),
        Padding(
          padding: EdgeInsetsDirectional.only(
            start: 16,
            end: useMaterial3 ? 24 : 16,
            bottom: 0,
          ),
          child: const TextFieldShowcase(),
        ),
        const Divider(),
        SwitchListTileReveal(
          enabled: enableControl,
          contentPadding: EdgeInsetsDirectional.only(
            start: 16,
            end: useMaterial3 ? 28 : 20,
          ),
          title: const Text('Background filled'),
          subtitleReveal: const Text('If you leave this OFF, you can still '
              'theme the fill color below and turn it ON by using the '
              'widget level "filled: true" property and it gets the '
              'themed fill style by default, but you can also use the not '
              'filled style. It also works the other way around, leave it '
              'ON and set to OFF on widget level when so needed.\n'),
          value: controller.inputDecoratorIsFilled,
          onChanged: controller.setInputDecoratorIsFilled,
        ),

        if (isLight)
          ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
            return RowOrColumn(
              firstWidget: ColorSchemePopupMenu(
                contentPadding: ThemeValues.tilePaddingStart(context, isRow),
                enabled: enableControl,
                title: const Text('Background color (light)'),
                defaultLabel: 'surfaceContainerHighest',
                defaultLabelM2: 'primary',
                defaultDisabledLabelM2: '#0A000000: 4% black',
                value: controller.inputDecoratorSchemeColorLight,
                onChanged: controller.setInputDecoratorSchemeColorLight,
              ),
              lastWidget: SliderListTileReveal(
                enabled: enableControl,
                contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                title: const Text('Opacity'),
                subtitle: Text('Alpha as opacity is '
                    '$lightBackgroundLabelOpacity %'),
                value:
                    controller.inputDecoratorBackgroundAlphaLight?.toDouble(),
                onChanged: (double? value) {
                  controller.setInputDecoratorBackgroundAlphaLight(
                      value == null || value < 0 ? null : value.toInt());
                },
                min: 0,
                max: 255,
                divisions: 255,
                valueDecimalPlaces: 0,
                valueHeading: 'ALPHA',
                valueDefaultLabel: lightBackgroundLabel,
              ),
              isRow: isRow,
            );
          })
        else
          ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
            return RowOrColumn(
              firstWidget: ColorSchemePopupMenu(
                contentPadding: ThemeValues.tilePaddingStart(context, isRow),
                enabled: enableControl,
                title: const Text('Background color (dark)'),
                defaultLabel: 'surfaceContainerHighest',
                defaultLabelM2: 'primary',
                defaultDisabledLabelM2: '#1AFFFFFF: 10% white',
                value: controller.inputDecoratorSchemeColorDark,
                onChanged: controller.setInputDecoratorSchemeColorDark,
              ),
              lastWidget: SliderListTileReveal(
                enabled: enableControl,
                contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                title: const Text('Opacity'),
                subtitle: Text('Alpha as opacity is '
                    '$darkBackgroundLabelOpacity %'),
                value: controller.inputDecoratorBackgroundAlphaDark?.toDouble(),
                onChanged: (double? value) {
                  controller.setInputDecoratorBackgroundAlphaDark(
                      value == null || value < 0 ? null : value.toInt());
                },
                min: 0,
                max: 255,
                divisions: 255,
                valueDecimalPlaces: 0,
                valueHeading: 'ALPHA',
                valueDefaultLabel: darkBackgroundLabel,
              ),
              isRow: isRow,
            );
          }),
        const Divider(height: 0),
        //
        // Border type and radius
        //
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            firstWidget: ListTileReveal(
              contentPadding: ThemeValues.tilePaddingStart(context, isRow),
              enabled: enableControl,
              title: const Text('Border'),
              subtitle: controller.inputDecoratorBorderType ==
                          FlexInputBorderType.outline &&
                      enableControl
                  ? const Text('Outlined')
                  : const Text('Underlined'),
              onTap: () {
                if (controller.inputDecoratorBorderType ==
                    FlexInputBorderType.outline) {
                  controller.setInputDecoratorBorderType(
                      FlexInputBorderType.underline);
                } else {
                  controller
                      .setInputDecoratorBorderType(FlexInputBorderType.outline);
                }
              },
              trailing: Padding(
                padding: const EdgeInsetsDirectional.only(end: 12),
                child: controller.inputDecoratorBorderType ==
                            FlexInputBorderType.outline &&
                        enableControl
                    ? const Icon(Icons.border_outer_outlined, size: 36)
                    : const Icon(Icons.border_bottom_outlined, size: 36),
              ),
            ),
            lastWidget: EnumPopupMenu<AdaptiveResponse>(
              contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
              enabled: enableControl,
              values: AdaptiveResponse.values,
              title: const Text('Adaptive response'),
              subtitleReveal: Text(
                'Use an alternative InputDecorator border radius on '
                'selected platforms.\n'
                '\n'
                // ignore: lines_longer_than_80_chars, string interpolation
                '${controller.adaptiveResponseInputDecoratorRadius?.describe ?? AdaptiveResponse.off.describe}',
              ),
              defaultLabel: _adaptiveDecoratorModeLabel(controller),
              value: controller.adaptiveResponseInputDecoratorRadius,
              onChanged: controller.setAdaptiveResponseInputDecoratorRadius,
            ),
            isRow: isRow,
          );
        }),
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            isRow: isRow,
            firstWidget: SliderListTileReveal(
              contentPadding: ThemeValues.tilePaddingStart(context, isRow),
              enabled: enableControl,
              title: const Text('Border radius'),
              value: controller.inputDecoratorBorderRadius,
              onChanged: controller.setInputDecoratorBorderRadius,
              min: 0,
              max: 40,
              divisions: 40,
              valueDecimalPlaces: 0,
              valueHeading: 'RADIUS',
              valueUnitLabel: ' dp',
              valueDefaultLabel: decoratorRadiusDefaultLabel,
              valueDefaultDisabledLabel: '4 dp',
            ),
            lastWidget: SliderListTileReveal(
              contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
              enabled: enableControl &&
                  controller.adaptiveResponseInputDecoratorRadius !=
                      AdaptiveResponse.off &&
                  controller.adaptiveResponseInputDecoratorRadius != null,
              title: const Text('Adaptive radius'),
              value: controller.inputDecoratorBorderRadiusAdaptive,
              onChanged: controller.setInputDecoratorBorderRadiusAdaptive,
              min: 0,
              max: 40,
              divisions: 40,
              valueDecimalPlaces: 0,
              valueHeading: 'RADIUS',
              valueUnitLabel: ' dp',
              valueDefaultLabel: _adaptiveDecoratorRadiusLabel(controller),
              valueDefaultDisabledLabel: '4 dp',
            ),
          );
        }),
        TestAdaptiveResponse(controller),
        const Divider(),
        //
        // Border color and style
        //
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            firstWidget: isLight
                // 1st column light
                ? ColorSchemePopupMenu(
                    contentPadding:
                        ThemeValues.tilePaddingStart(context, isRow),
                    enabled: enableControl &&
                        !(!controller.inputDecoratorFocusedHasBorder &&
                            (!controller.inputDecoratorUnfocusedHasBorder ||
                                !controller
                                    .inputDecoratorUnfocusedBorderIsColored)),
                    title: const Text('Border color (light)'),
                    defaultLabel: baseDefaultLabelLightColor,
                    defaultDisabledLabel: 'primary',
                    value: controller.inputDecoratorBorderSchemeColorLight,
                    onChanged:
                        controller.setInputDecoratorBorderSchemeColorLight,
                  )
                // 1st column dark
                : ColorSchemePopupMenu(
                    contentPadding:
                        ThemeValues.tilePaddingStart(context, isRow),
                    enabled: enableControl &&
                        !(!controller.inputDecoratorFocusedHasBorder &&
                            (!controller.inputDecoratorUnfocusedHasBorder ||
                                !controller
                                    .inputDecoratorUnfocusedBorderIsColored)),
                    title: const Text('Border color (dark)'),
                    defaultDisabledLabel: 'primary',
                    defaultLabel: baseDefaultLabelDarkColor,
                    value: controller.inputDecoratorBorderSchemeColorDark,
                    onChanged:
                        controller.setInputDecoratorBorderSchemeColorDark,
                  ),
            lastWidget: SwitchListTileReveal(
              contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
              title: const Text('Unfocused uses color'),
              value: enableControl &&
                  controller.inputDecoratorUnfocusedBorderIsColored &&
                  controller.inputDecoratorUnfocusedHasBorder,
              onChanged: controller.useSubThemes &&
                      controller.inputDecoratorUnfocusedHasBorder &&
                      controller.useFlexColorScheme
                  ? controller.setInputDecoratorUnfocusedBorderIsColored
                  : null,
            ),
            isRow: isRow,
          );
        }),
        //
        // Unfocused border
        //
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            firstWidget: SwitchListTileReveal(
              contentPadding: ThemeValues.tilePaddingStart(context, isRow),
              title: const Text('Unfocused has border'),
              value:
                  enableControl && controller.inputDecoratorUnfocusedHasBorder,
              onChanged: enableControl
                  ? controller.setInputDecoratorUnfocusedHasBorder
                  : null,
            ),
            lastWidget: SliderListTileReveal(
              contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
              enabled:
                  enableControl && controller.inputDecoratorUnfocusedHasBorder,
              title: const Text('Unfocused border width'),
              value: controller.inputDecoratorBorderWidth,
              onChanged: controller.setInputDecoratorBorderWidth,
              min: 0.5,
              max: 6,
              divisions: 11,
              valueDecimalPlaces: 1,
              valueHeading: 'WIDTH',
              valueDefaultLabel: unfocusedBorderDefaultLabel,
              valueDefaultDisabledLabel: '1 dp',
              valueUnitLabel: ' dp',
            ),
            isRow: isRow,
          );
        }),
        //
        // Focused border
        //
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            firstWidget: SwitchListTileReveal(
              contentPadding: ThemeValues.tilePaddingStart(context, isRow),
              title: const Text('Focused has border'),
              value: enableControl && controller.inputDecoratorFocusedHasBorder,
              onChanged:
                  controller.useSubThemes && controller.useFlexColorScheme
                      ? controller.setInputDecoratorFocusedHasBorder
                      : null,
            ),
            lastWidget: SliderListTileReveal(
              contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
              enabled:
                  enableControl && controller.inputDecoratorFocusedHasBorder,
              title: const Text('Focused border width'),
              value: controller.inputDecoratorFocusedBorderWidth,
              onChanged: controller.setInputDecoratorFocusedBorderWidth,
              min: 0.5,
              max: 6,
              divisions: 11,
              valueDecimalPlaces: 1,
              valueHeading: 'WIDTH',
              valueDefaultLabel: focusedBorderDefaultLabel,
              valueDefaultDisabledLabel: '2 dp',
              valueUnitLabel: ' dp',
            ),
            isRow: isRow,
          );
        }),
        const Divider(),
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            firstWidget: isLight
                // 1st column light
                ? ColorSchemePopupMenu(
                    contentPadding:
                        ThemeValues.tilePaddingStart(context, isRow),
                    enabled: enableControl,
                    title: const Text('Focused prefix icon'),
                    defaultLabel: 'onSurfaceVariant',
                    defaultLabelM2:
                        controller.inputDecoratorSchemeColorLight?.name ??
                            'primary',
                    defaultDisabledLabelM2: 'primary',
                    value: controller.inputDecoratorPrefixIconLightSchemeColor,
                    onChanged:
                        controller.setInputDecoratorPrefixIconLightSchemeColor,
                  )
                // 1st column dark
                : ColorSchemePopupMenu(
                    contentPadding:
                        ThemeValues.tilePaddingStart(context, isRow),
                    enabled: enableControl,
                    title: const Text('Focused prefix icon'),
                    defaultLabel: 'onSurfaceVariant',
                    defaultLabelM2:
                        controller.inputDecoratorSchemeColorDark?.name ??
                            'primary',
                    defaultDisabledLabelM2: 'primary',
                    value: controller.inputDecoratorPrefixIconDarkSchemeColor,
                    onChanged:
                        controller.setInputDecoratorPrefixIconDarkSchemeColor,
                  ),
            lastWidget: isLight
                // 2nd column light
                ? ColorSchemePopupMenu(
                    enabled: enableControl,
                    contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                    title: const Text('Focused suffix icon'),
                    defaultLabel: 'onSurfaceVariant',
                    defaultLabelM2:
                        controller.inputDecoratorSchemeColorLight?.name ??
                            'primary',
                    defaultDisabledLabelM2: 'primary',
                    value: controller.inputDecoratorSuffixIconLightSchemeColor,
                    onChanged:
                        controller.setInputDecoratorSuffixIconLightSchemeColor,
                  )
                // 2nd column dark
                : ColorSchemePopupMenu(
                    enabled: enableControl,
                    contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                    title: const Text('Focused suffix icon'),
                    defaultLabel: 'onSurfaceVariant',
                    defaultLabelM2:
                        controller.inputDecoratorSchemeColorDark?.name ??
                            'primary',
                    defaultDisabledLabelM2: 'primary',
                    value: controller.inputDecoratorSuffixIconDarkSchemeColor,
                    onChanged:
                        controller.setInputDecoratorSuffixIconDarkSchemeColor,
                  ),
            isRow: isRow,
          );
        }),
        const Divider(),
        //
        // TextField Padding props
        //
        SwitchListTileReveal(
          enabled: enableControl,
          title: const Text('Dense TextField '),
          subtitleReveal: const Text(
            'A nice Flutter built in quick padding '
            'style toggle to make the TextField more dense and use less '
            'padding. Many prefer the dense less space wasting style.\n',
          ),
          value: controller.inputDecoratorIsDense,
          onChanged: controller.setInputDecoratorIsDense,
        ),
        ListTileReveal(
          enabled: enableControl,
          title: const Text('Content padding'),
          subtitleReveal: const Text(
            'When you toggle M2/M3, filled, border type and dense TextField, '
            'the default Flutter content padding values are shown, if they are '
            'all left undefined. There are also internal constraints '
            'in the InputDecorator impacting effective paddings, changing '
            'them from the shown defaults in some cases.\n'
            '\n'
            'Recommend caution when using custom content padding, but since '
            'you can visually see what you get here with different combos, '
            'feel free to experiment.\n',
          ),
        ),
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            firstWidget: SliderListTileReveal(
              contentPadding: ThemeValues.tilePaddingStart(context, isRow),
              trailingWidth: 52,
              enabled: enableControl,
              value: controller.inputDecoratorPaddingStart,
              onChanged: controller.setInputDecoratorPaddingStart,
              min: 0,
              max: 32,
              divisions: 32,
              valueDecimalPlaces: 0,
              valueHeading: 'START',
              valueUnitLabel: ' dp',
              valueDefaultLabel: DecoratorDefault.start.asLabel(controller),
            ),
            lastWidget: SliderListTileReveal(
              contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
              trailingWidth: 60,
              enabled: enableControl,
              value: controller.inputDecoratorPaddingEnd,
              onChanged: controller.setInputDecoratorPaddingEnd,
              min: 0,
              max: 32,
              divisions: 32,
              valueDecimalPlaces: 0,
              valueHeading: 'END',
              valueUnitLabel: ' dp',
              valueDefaultLabel: DecoratorDefault.end.asLabel(controller),
            ),
            isRow: isRow,
          );
        }),
        ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
          return RowOrColumn(
            firstWidget: SliderListTileReveal(
              contentPadding: ThemeValues.tilePaddingStart(context, isRow),
              trailingWidth: 52,
              enabled: enableControl,
              value: controller.inputDecoratorPaddingTop,
              onChanged: controller.setInputDecoratorPaddingTop,
              min: 0,
              max: 32,
              divisions: 32,
              valueDecimalPlaces: 0,
              valueHeading: 'TOP',
              valueUnitLabel: ' dp',
              valueDefaultLabel: DecoratorDefault.top.asLabel(controller),
            ),
            lastWidget: SliderListTileReveal(
              contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
              trailingWidth: 60,
              enabled: enableControl,
              value: controller.inputDecoratorPaddingBottom,
              onChanged: controller.setInputDecoratorPaddingBottom,
              min: 0,
              max: 32,
              divisions: 32,
              valueDecimalPlaces: 0,
              valueHeading: 'BOTTOM',
              valueUnitLabel: ' dp',
              valueDefaultLabel: DecoratorDefault.bottom.asLabel(controller),
            ),
            isRow: isRow,
          );
        }),
        //
        const SizedBox(height: 8),
        const Divider(height: 0),
        //
        // Text Selection Style
        //
        if (isLight)
          ListTile(
            title: const Text('TextSelection style (light)'),
            tileColor: theme.colorScheme.surfaceContainer,
          )
        else
          ListTile(
            title: const Text('TextSelection style (dark)'),
            tileColor: theme.colorScheme.surfaceContainer,
          ),
        const Divider(height: 0),
        const Padding(
          padding: EdgeInsetsDirectional.only(start: 16, end: 108, top: 16),
          child: TextField(
            showCursor: true,
            decoration: InputDecoration(
              hintText: 'Write something to try text selection style',
              labelText: 'TextField selection',
            ),
          ),
        ),
        if (isLight) ...<Widget>[
          ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
            return RowOrColumn(
              firstWidget: ColorSchemePopupMenu(
                contentPadding: ThemeValues.tilePaddingStart(context, isRow),
                enabled: enableControl,
                title: const Text('Cursor'),
                defaultLabel: baseDefaultLabelLightColor,
                defaultDisabledLabel: 'primary',
                value: controller.inputCursorLightSchemeColor,
                onChanged: controller.setInputCursorLightSchemeColor,
              ),
              lastWidget: ColorSchemePopupMenu(
                contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                enabled: enableControl,
                title: const Text('Selection handles'),
                defaultLabel: baseDefaultHandleLabelLightColor,
                defaultDisabledLabel: 'primary',
                value: controller.inputSelectionHandleLightSchemeColor,
                onChanged: controller.setInputSelectionHandleLightSchemeColor,
              ),
              isRow: isRow,
            );
          }),
          ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
            return RowOrColumn(
              firstWidget: ColorSchemePopupMenu(
                contentPadding: ThemeValues.tilePaddingStart(context, isRow),
                enabled: enableControl,
                title: const Text('Selection'),
                defaultLabel: baseDefaultLabelLightColor,
                defaultDisabledLabel: 'primary',
                value: controller.inputSelectionLightSchemeColor,
                onChanged: controller.setInputSelectionLightSchemeColor,
              ),
              lastWidget: SliderListTileReveal(
                contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                enabled: enableControl,
                title: const Text('Selection opacity'),
                value: controller.inputSelectionLightOpacity,
                onChanged: controller.setInputSelectionLightOpacity,
                min: 0,
                max: 1,
                divisions: 100,
                valueDisplayScale: 100,
                valueDecimalPlaces: 0,
                valueHeading: 'OPACITY',
                valueUnitLabel: ' %',
                valueDefaultLabel: selectionLabelDefaultOpacity,
                valueDefaultDisabledLabel: '40 %',
              ),
              isRow: isRow,
            );
          }),
        ] else ...<Widget>[
          ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
            return RowOrColumn(
              firstWidget: ColorSchemePopupMenu(
                contentPadding: ThemeValues.tilePaddingStart(context, isRow),
                enabled: enableControl,
                title: const Text('Cursor'),
                defaultLabel: baseDefaultLabelDarkColor,
                defaultDisabledLabel: 'primary',
                value: controller.inputCursorDarkSchemeColor,
                onChanged: controller.setInputCursorDarkSchemeColor,
              ),
              lastWidget: ColorSchemePopupMenu(
                contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                enabled: enableControl,
                title: const Text('Selection handles'),
                defaultLabel: baseDefaultHandleLabelDarkColor,
                defaultDisabledLabel: 'primary',
                value: controller.inputSelectionHandleDarkSchemeColor,
                onChanged: controller.setInputSelectionHandleDarkSchemeColor,
              ),
              isRow: isRow,
            );
          }),
          ResponsiveTwoWidgets(builder: (BuildContext context, bool isRow) {
            return RowOrColumn(
              firstWidget: ColorSchemePopupMenu(
                contentPadding: ThemeValues.tilePaddingStart(context, isRow),
                enabled: enableControl,
                title: const Text('Selection'),
                defaultLabel: baseDefaultLabelDarkColor,
                defaultDisabledLabel: 'primary',
                value: controller.inputSelectionDarkSchemeColor,
                onChanged: controller.setInputSelectionDarkSchemeColor,
              ),
              lastWidget: SliderListTileReveal(
                contentPadding: ThemeValues.tilePaddingEnd(context, isRow),
                enabled: enableControl,
                title: const Text('Selection opacity'),
                value: controller.inputSelectionDarkOpacity,
                onChanged: controller.setInputSelectionDarkOpacity,
                min: 0,
                max: 1,
                divisions: 100,
                valueDisplayScale: 100,
                valueDecimalPlaces: 0,
                valueHeading: 'OPACITY',
                valueUnitLabel: ' %',
                valueDefaultLabel: selectionLabelDefaultOpacity,
                valueDefaultDisabledLabel: '40 %',
              ),
              isRow: isRow,
            );
          }),
        ],
        //
        // Known issues
        //
        ListTileReveal(
          dense: true,
          title: const Text('Known issues'),
          subtitleReveal: RichText(
            text: TextSpan(
              children: <TextSpan>[
                TextSpan(
                  style: spanTextStyle,
                  text: 'The text selection handle color cannot be changed '
                      'using a global theme when using Material TextField on '
                      'iOS platforms. They can only be primary color, see API '
                      'doc ',
                ),
                LinkTextSpan(
                  style: linkStyle,
                  uri: _fcsFlutterHandleLimit,
                  text: 'selectionHandleColor property',
                ),
                TextSpan(
                  style: spanTextStyle,
                  text: ' for more information. consider making an '
                      'improvement proposal issue in the Flutter '
                      'repo if you want this to change.\n',
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}
