content: import 'package:flex_color_scheme/flex_color_scheme.dart';
  import 'package:flutter/material.dart';
  
  import '../../../shared/widgets/universal/list_tile_reveal.dart';
  import 'color_scheme_box.dart';
  
  /// Widget used to select ColorScheme based colors via a
  /// [FlexScaffoldBaseColor] enum.
  ///
  /// Uses null [value] of [FlexScaffoldBaseColor] to represent and select
  /// no selection of [FlexScaffoldBaseColor] which represents default
  /// color behavior for the widget using the selected color.
  ///
  /// The user can pass in different labels to use as default label value, when
  /// the widget is:
  ///
  /// * enabled: [defaultLabel] if not provided defaults to 'unknown'.
  /// * enabled darkMode: [defaultLabelDark], if not provided uses [defaultLabel].
  /// * enabled in M2 mode: [defaultLabelM2], if not provided uses [defaultLabel].
  /// * enabled in M2 darkMode, if not provided uses [defaultLabelDark].
  /// * disabled: [defaultDisabledLabel], if not provided uses [defaultLabel].
  /// * disabled darkMode: [defaultDisabledLabelDark], if not provided
  ///   uses [defaultDisabledLabel].
  /// * disabled in M2 mode: [defaultDisabledLabelM2], if not provided uses
  ///   [defaultDisabledLabel].
  /// * disabled in M2 darkMode, if not provided uses [defaultDisabledLabelDark].
  class ScaffoldBasePopupMenu extends StatelessWidget {
    const ScaffoldBasePopupMenu({
      super.key,
      this.value,
      this.onChanged,
      this.enabled = true,
      this.title,
      this.subtitle,
      this.subtitleReveal,
      this.colorPrefix = '',
      this.colorSuffix = '',
      this.contentPadding,
      this.dense,
      this.revealDense,
      this.defaultLabel,
      this.defaultLabelDark,
      this.defaultLabelM2,
      this.defaultLabelDarkM2,
      this.defaultDisabledLabel,
      this.defaultDisabledLabelDark,
      this.defaultDisabledLabelM2,
      this.defaultDisabledLabelDarkM2,
      this.wrapWithDefaultLabel = true,
    });
  
    /// The currently selected FlexScaffoldBaseColor value for this popup.
    ///
    /// A null value represents the default value selection.
    final FlexScaffoldBaseColor? value;
  
    /// Called when a new FlexScaffoldBaseColor is selected.
    ///
    /// The default value selection calls this with null value.
    /// The other with the choice corresponding to the selected enum value.
    final ValueChanged<FlexScaffoldBaseColor?>? onChanged;
  
    /// Whether this PopupMenu is enabled.
    ///
    /// Set to false to disable the popup, it will be displayed as disabled
    /// along with the title and value trailing labels.
    final bool enabled;
  
    /// The main heading content of the Slider tile.
    ///
    /// Typically a [Text] widget.
    final Widget? title;
  
    /// Additional content displayed below the title.
    ///
    /// Typically a [Text] widget.
    final Widget? subtitle;
  
    /// Additional content displayed below the subtitle in a reveal animation.
    ///
    /// Typically a [Text] widget.
    final Widget? subtitleReveal;
  
    /// A prefix to the color name displayed in the subtitle of the selected item.
    ///
    /// If provided, this text label is added before the selected color value
    /// displayed in the  subtitle of the selected item ListTile label.
    final String colorPrefix;
  
    /// A suffix to the color name displayed in the subtitle of the selected item.
    ///
    /// If provided, this text label is added after the selected color value
    /// displayed in the  subtitle of the selected item ListTile label.
    final String colorSuffix;
  
    /// The [ListTileReveal]'s internal padding.
    ///
    /// Insets a [ListTileReveal]'s contents.
    ///
    /// If null, `EdgeInsets.symmetric(horizontal: 16.0)` is used in M2
    /// and `EdgeInsetsDirectional.only(start: 16.0, end: 24.0)` in M3.
    final EdgeInsetsGeometry? contentPadding;
  
    /// Whether this list tile is part of a vertically dense list.
    ///
    /// If this property is null then its value is based on [ListTileTheme.dense].
    ///
    /// Dense list tiles default to a smaller height.
    final bool? dense;
  
    /// Whether the used reveal part of the ListTile is dense.
    ///
    /// If not defined, defaults to true.
    final bool? revealDense;
  
    /// The label to display when [value] is null representing the
    /// default color value.
    ///
    /// If not defined, defaults to 'unknown'.
    final String? defaultLabel;
  
    /// The label to display when [value] is null in dark mode, representing the
    /// default color value.
    ///
    /// If not defined defaults to [defaultLabel].
    final String? defaultLabelDark;
  
    /// The label to display when [value] is null in M2 mode, representing the
    /// default color value.
    ///
    /// If not defined defaults to [defaultLabel].
    final String? defaultLabelM2;
  
    /// The label to display when [value] is null in M2 dark mode, representing
    /// the default color value.
    ///
    /// If not defined defaults to [defaultLabelM2], if not defined then to
    /// [defaultLabelDark], that if it is not defined defaults to [defaultLabel].
    ///
    /// M2 mode prioritize M2 defaults over dark dark defaults.
    final String? defaultLabelDarkM2;
  
    /// The label to display when [value] is null when the control is disabled,
    /// representing the default color value then.
    ///
    /// If not defined defaults to [defaultLabel].
    final String? defaultDisabledLabel;
  
    /// The label to display when [value] is null when the control is disabled
    /// in dark mode, representing the default color value then.
    ///
    /// If not defined defaults to [defaultDisabledLabel].
    final String? defaultDisabledLabelDark;
  
    /// The label to display when [value] is null when the control is disabled,
    /// in M2 mode, representing the default color value then.
    ///
    /// If not defined defaults to [defaultDisabledLabel].
    final String? defaultDisabledLabelM2;
  
    /// The label to display when [value] is null when the control is disabled
    /// in M2 mode,
    /// representing the default color value then.
    ///
    /// If not defined defaults to [defaultDisabledLabelM2], if not defined then
    /// to [defaultDisabledLabelDark], that if it is not defined defaults to
    /// [defaultDisabledLabel], which default to [defaultLabel].
    ///
    /// M2 mode prioritize M2 defaults over dark dark defaults.
    final String? defaultDisabledLabelDarkM2;
  
    /// When set to true, wraps the resolved default label with the
    /// text 'default ($resolvedLabel)'.
    ///
    /// If false there is no such wrapping, the default label is used as is.
    ///
    /// Defaults to true.
    final bool wrapWithDefaultLabel;
  
    @override
    Widget build(BuildContext context) {
      final ThemeData theme = Theme.of(context);
      final bool useMaterial3 = theme.useMaterial3;
      final bool isLight = theme.brightness == Brightness.light;
      final ColorScheme colorScheme = theme.colorScheme;
      final TextStyle txtStyle = theme.textTheme.labelLarge!;
  
      final String usedLabel = defaultLabel ?? 'unknown';
      final String usedLabelM2 = defaultLabelM2 ?? usedLabel;
      final String usedLabelDark = defaultLabelDark ?? usedLabel;
      final String usedLabelDarkM2 =
          defaultLabelDarkM2 ?? defaultLabelM2 ?? defaultLabelDark ?? usedLabel;
  
      final String resolvedEnabledLabel = useMaterial3
          ? isLight
              ? usedLabel
              : usedLabelDark
          : isLight
              ? usedLabelM2
              : usedLabelDarkM2;
  
      final String disabledLabel = defaultDisabledLabel ?? usedLabel;
      final String disabledLabelDark = defaultDisabledLabelDark ??
          defaultDisabledLabel ??
          defaultLabelDark ??
          usedLabel;
      final String disabledLabelM2 = defaultDisabledLabelM2 ??
          defaultDisabledLabel ??
          defaultLabelM2 ??
          usedLabel;
      final String disabledLabelDarkM2 = defaultDisabledLabelDarkM2 ??
          defaultDisabledLabelM2 ??
          defaultDisabledLabelDark ??
          defaultDisabledLabel ??
          defaultLabelDark ??
          defaultLabelM2 ??
          usedLabel;
  
      final String resolvedDisabledLabel = useMaterial3
          ? isLight
              ? disabledLabel
              : disabledLabelDark
          : isLight
              ? disabledLabelM2
              : disabledLabelDarkM2;
  
      final String resolvedLabel =
          enabled ? resolvedEnabledLabel : resolvedDisabledLabel;
  
      final String effectiveDefaultLabel =
          wrapWithDefaultLabel ? 'default ($resolvedLabel)' : resolvedLabel;
  
      final String selectedLabel = enabled && value != null
          ? value?.getName(isLight) ?? ''
          : effectiveDefaultLabel;
  
      return Theme(
        data: Theme.of(context).copyWith(
          scrollbarTheme: Theme.of(context).scrollbarTheme.copyWith(
                thumbVisibility: WidgetStateProperty.all<bool>(true),
              ),
        ),
        child: PopupMenuButton<int>(
          popUpAnimationStyle: AnimationStyle.noAnimation,
          position: PopupMenuPosition.under,
          offset: const Offset(0, -4),
          constraints: const BoxConstraints(
            minWidth: 300,
            maxWidth: 300,
            maxHeight: 600,
          ),
          initialValue: !enabled || value == null ? 0 : value!.index + 1,
          tooltip: '',
          padding: EdgeInsets.zero,
          onSelected: (int index) {
            onChanged?.call(
                index == 0 ? null : FlexScaffoldBaseColor.values[index - 1]);
          },
          enabled: enabled,
          itemBuilder: (BuildContext context) => <PopupMenuItem<int>>[
            for (int i = 0; i <= FlexScaffoldBaseColor.values.length; i++)
              PopupMenuItem<int>(
                value: i,
                child: ListTile(
                  dense: true,
                  contentPadding: EdgeInsets.zero,
                  leading: ColorSchemeBox(
                    foregroundColor: (value?.index ?? -1) + 1 == i
                        ? colorScheme.onSurface
                        : colorScheme.onSurfaceVariant,
                    backgroundColor: i <= 0
                        ? colorScheme.surface
                        : FlexScaffoldBaseColor.values[i - 1].color(
                            colorScheme,
                            useMaterial3: useMaterial3,
                          ),
                    selected: (value?.index ?? -1) + 1 == i,
                    borderColor: (value?.index ?? -1) + 1 == i
                        ? theme.colorScheme.onSurface
                        : theme.colorScheme.outline,
                    defaultOption: i <= 0,
                  ),
                  title: i <= 0
                      ? Text(effectiveDefaultLabel, style: txtStyle)
                      : Text(FlexScaffoldBaseColor.values[i - 1].getName(isLight),
                          style: txtStyle),
                ),
              )
          ],
          child: ListTileReveal(
            enabled: enabled,
            dense: dense,
            revealDense: revealDense,
            contentPadding: contentPadding,
            title: title,
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text('$colorPrefix$selectedLabel$colorSuffix'),
                if (subtitle != null) subtitle!,
              ],
            ),
            subtitleReveal: subtitleReveal,
            trailing: Padding(
              padding: const EdgeInsetsDirectional.only(end: 5.0),
              child: ColorSchemeBox(
                foregroundColor: enabled
                    ? colorScheme.onSurface
                    : colorScheme.onSurface.withValues(alpha: enabled ? 1 : 0.5),
                backgroundColor: enabled && value != null
                    ? value!.color(
                        colorScheme,
                        useMaterial3: useMaterial3,
                      )
                    : colorScheme.surface,
                borderColor:
                    colorScheme.outline.withValues(alpha: enabled ? 1 : 0.5),
                defaultOption: value == null,
              ),
            ),
          ),
        ),
      );
    }
  }
  