import 'package:baseproject/assets/images.dart';
import 'package:baseproject/core/components/constants_widget.dart';
import 'package:baseproject/core/components/form/form_builder_field.dart';
import 'package:baseproject/core/components/index.dart';
import 'package:baseproject/core/theme/custom_color.dart';
import 'package:baseproject/core/theme/text_style.dart';
import 'package:collection/collection.dart' show IterableExtension;

import 'package:flutter/material.dart';

/// Field for Dropdown button
class CustomSelect<T> extends FormBuilderField<T> {
  /// The list of items the user can select.
  ///
  /// If the [onChanged] callback is null or the list of items is null
  /// then the dropdown button will be disabled, i.e. its arrow will be
  /// displayed in grey and it will not respond to input. A disabled button
  /// will display the [disabledHint] widget if it is non-null. If
  /// [disabledHint] is also null but [hint] is non-null, [hint] will instead
  /// be displayed.
  final List<DropdownMenuItem<T>> items;

  /// A placeholder widget that is displayed by the dropdown button.
  ///
  /// If [value] is null, this widget is displayed as a placeholder for
  /// the dropdown button's value. This widget is also displayed if the button
  /// is disabled ([items] or [onChanged] is null) and [disabledHint] is null.
  final Widget? hint;

  /// A message to show when the dropdown is disabled.
  ///
  /// Displayed if [items] or [onChanged] is null. If [hint] is non-null and
  /// [disabledHint] is null, the [hint] widget will be displayed instead.
  final Widget? disabledHint;

  /// Called when the dropdown button is tapped.
  ///
  /// This is distinct from [onChanged], which is called when the user
  /// selects an item from the dropdown.
  ///
  /// The callback will not be invoked if the dropdown button is disabled.
  final VoidCallback? onTap;

  /// A builder to customize the dropdown buttons corresponding to the
  /// [DropdownMenuItem]s in [items].
  ///
  /// When a [DropdownMenuItem] is selected, the widget that will be displayed
  /// from the list corresponds to the [DropdownMenuItem] of the same index
  /// in [items].
  ///
  /// {@tool dartpad --template=stateful_widget_scaffold}
  ///
  /// This sample shows a `DropdownButton` with a button with [Text] that
  /// corresponds to but is unique from [DropdownMenuItem].
  ///
  /// If this callback is null, the [DropdownMenuItem] from [items]
  /// that matches [value] will be displayed.
  final DropdownButtonBuilder? selectedItemBuilder;

  /// The z-coordinate at which to place the menu when open.
  ///
  /// The following elevations have defined shadows: 1, 2, 3, 4, 6, 8, 9, 12,
  /// 16, and 24. See [kElevationToShadow].
  ///
  /// Defaults to 8, the appropriate elevation for dropdown buttons.
  final int elevation;

  /// {@end-tool}
  ///
  /// Defaults to the [TextTheme.subtitle1] value of the current
  /// [ThemeData.textTheme] of the current [Theme].
  final TextStyle? style;

  /// The widget to use for the drop-down button's icon.
  ///
  /// Defaults to an [Icon] with the [Icons.arrow_drop_down] glyph.
  final Widget? icon;

  /// The color of any [Icon] descendant of [icon] if this button is disabled,
  /// i.e. if [onChanged] is null.
  ///
  /// Defaults to [Colors.grey.shade400] when the theme's
  /// [ThemeData.brightness] is [Brightness.light] and to
  /// [Colors.white10] when it is [Brightness.dark]
  final Color? iconDisabledColor;

  /// The color of any [Icon] descendant of [icon] if this button is enabled,
  /// i.e. if [onChanged] is defined.
  ///
  /// Defaults to [Colors.grey.shade700] when the theme's
  /// [ThemeData.brightness] is [Brightness.light] and to
  /// [Colors.white70] when it is [Brightness.dark]
  final Color? iconEnabledColor;

  /// The size to use for the drop-down button's down arrow icon button.
  ///
  /// Defaults to 24.0.
  final double iconSize;

  /// Reduce the button's height.
  ///
  /// By default this button's height is the same as its menu items' heights.
  /// If isDense is true, the button's height is reduced by about half. This
  /// can be useful when the button is embedded in a container that adds
  /// its own decorations, like [InputDecorator].
  final bool isDense;

  /// Set the dropdown's inner contents to horizontally fill its parent.
  ///
  /// By default this button's inner width is the minimum size of its contents.
  /// If [isExpanded] is true, the inner width is expanded to fill its
  /// surrounding container.
  final bool isExpanded;

  /// If null, then the menu item heights will vary according to each menu item's
  /// intrinsic height.
  ///
  /// The default value is [kMinInteractiveDimension], which is also the minimum
  /// height for menu items.
  ///
  /// If this value is null and there isn't enough vertical room for the menu,
  /// then the menu's initial scroll offset may not align the selected item with
  /// the dropdown button. That's because, in this case, the initial scroll
  /// offset is computed as if all of the menu item heights were
  /// [kMinInteractiveDimension].
  final double itemHeight;

  /// The color for the button's [Material] when it has the input focus.
  final Color? focusColor;

  /// {@macro flutter.widgets.Focus.autofocus}
  final bool autofocus;

  /// The background color of the dropdown.
  ///
  /// If it is not provided, the theme's [ThemeData.canvasColor] will be used
  /// instead.
  final Color? dropdownColor;

  final bool allowClear;
  final Widget clearIcon;

  /// Creates field for Dropdown button
  CustomSelect({
    Key? key,
    //From Super
    String name = "select",
    FormFieldValidator<T>? validator,
    T? initialValue,
    InputDecoration decoration = const InputDecoration(),
    ValueChanged<T?>? onChanged,
    ValueTransformer<T?>? valueTransformer,
    bool enabled = true,
    FormFieldSetter<T>? onSaved,
    AutovalidateMode autovalidateMode = AutovalidateMode.disabled,
    VoidCallback? onReset,
    FocusNode? focusNode,
    required this.items,
    this.isExpanded = true,
    this.isDense = true,
    this.elevation = 8,
    this.iconSize = 24.0,
    this.hint,
    this.style,
    this.disabledHint,
    this.icon,
    this.iconDisabledColor,
    this.iconEnabledColor,
    this.allowClear = false,
    this.clearIcon = const Icon(
      Icons.close,
      size: 18,
      color: CustomColor.textGray,
    ),
    this.onTap,
    this.autofocus = false,
    this.dropdownColor,
    this.focusColor,
    this.itemHeight = kMinInteractiveDimension,
    this.selectedItemBuilder,
  }) : /*: assert(allowClear == true || clearIcon != null)*/ super(
          key: key,
          initialValue: initialValue,
          name: name,
          validator: validator,
          valueTransformer: valueTransformer,
          onChanged: onChanged,
          autovalidateMode: autovalidateMode,
          onSaved: onSaved,
          enabled: enabled,
          onReset: onReset,
          decoration: decoration,
          focusNode: focusNode,
          builder: (FormFieldState<T?> field) {
            final _SelectState<T> state = field as _SelectState<T>;
            // DropdownButtonFormField
            // TextFormField

            void changeValue(T? value) {
              state.didChange(value);
            }

            return InputDecorator(
              decoration: state.decoration().copyWith(
                    floatingLabelBehavior:
                        hint == null ? decoration.floatingLabelBehavior : FloatingLabelBehavior.always,
                    filled: true,
                    fillColor: CustomColor.bgGrayLight,
                  ),
              isEmpty: state.value == null,
              child: Row(
                children: <Widget>[
                  Expanded(
                    child: DropdownButtonHideUnderline(
                      child: DropdownButton<T>(
                        isExpanded: isExpanded,
                        hint: hint,
                        items: items,
                        value: field.value, //field.value,
                        style: style,
                        isDense: isDense,
                        disabledHint: field.value != null
                            ? (items.firstWhereOrNull((val) => val.value == field.value)?.child ??
                                Text(field.value.toString()))
                            : disabledHint,
                        elevation: elevation,
                        iconSize: iconSize,
                        // icon: icon ?? svgImage(Images.icArrowDown, color: CustomColor.textGray, height: 8),
                        iconDisabledColor: iconDisabledColor,
                        iconEnabledColor: iconEnabledColor,
                        onChanged: state.enabled ? (T? value) => changeValue(value) : null,
                        onTap: onTap,
                        focusNode: state.effectiveFocusNode,
                        autofocus: autofocus,
                        dropdownColor: dropdownColor,
                        focusColor: focusColor,
                        itemHeight: itemHeight,
                        selectedItemBuilder: selectedItemBuilder,
                      ),
                    ),
                  ),
                  if (allowClear && state.enabled && field.value != null) ...[
                    ConstantWidget.widthSpace10,
                    InkWell(
                      onTap: () => changeValue(null),
                      child: clearIcon,
                    ),
                  ]
                ],
              ),
            );
          },
        );

  @override
  _SelectState<T> createState() => _SelectState<T>();
}

class _SelectState<T> extends FormBuilderFieldState<CustomSelect<T>, T> {}
