/*
 * @Author: XianKaiQun
 * @Date: 2020-08-25 14:59:08
 * @LastEditors  : WuWei
 * @LastEditTime : 2023-05-23 11:40:04
 * @Description: 
 */
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wisdom_cli/wisdom_cli.dart';

///[value]当前的每一层级已选中的项组成的[List],
///[trigger] 触发弹出弹层的函数。
typedef WInfinityPickerFieldBuilder<T> = Widget Function(
  List<T> value,
  Future<void> Function() trigger,
);
typedef WInfinityPickerFieldOnChanged<T> = void Function(List<T>? value);

///无限单选
///
///在此高阶组件中已实现调用[WPickerUtil.infinity]与[Widget]间的调用，
///
///所以你只需要关注[builder]输出的什么Widget即可。
///
///
class WInfinityPickerField<T extends WPickerEntity> extends StatefulWidget {
  WInfinityPickerField({
    Key? key,
    required this.getData,
    required this.isLast,
    required this.builder,
    this.title,
    this.value,
    this.onChanged,
  }) : super(key: key);
  final Future<bool> Function(List<T>) isLast;

  final WInfinityPickerFieldBuilder<T> builder;
  final Widget? title;

  ///[getData]
  ///
  ///[selects]是每一个层级中已选择的项组成的[List],
  ///[selects]可能是[null]，也可能[List.length==0],
  ///所以一定要正确的将[selects]作为条件，并输出正确的[List<T>]。
  final Future<List<T>> Function(List<T> item) getData;

  ///初始化每一个层级中已选的项组成的[List]。
  final List<T>? value;

  final WInfinityPickerFieldOnChanged<T>? onChanged;

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

class _WInfinityPickerFieldState<T extends WPickerEntity>
    extends State<WInfinityPickerField<T>> {
  List<T>? _value;

  List<T> get value => _value ?? [];

  @override
  void initState() {
    super.initState();
    _value = widget.value;
  }

  ///触发单选弹出层
  Future<void> _trigger() async {
    final res = await WPickerUtil.infinity<T>(
      context,
      title: widget.title,
      getData: widget.getData,
      initialValue: _value ?? [],
      isLast: widget.isLast,
    );
    if (res != null) {
      _onChanged(res);
    }
  }

  ///触发[widget.onChanged],
  ///刷新视图[widget.builder]
  void _onChanged(List<T>? value) {
    if (_value == value) return;
    _value = value!;
    setState(() {});
    if (widget.onChanged != null) {
      widget.onChanged!(value);
    }
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(value, () => _trigger());
  }
}

///无限单选--表单项。
///
///基于[WInfinityPickerField]，和[WFormField]。
///
///[WInfinityPickerFormField.textField],
///使用[TextField]替代了[WInfinityPickerField.builder]方法
///
class WInfinityPickerFormField<T extends WPickerEntity>
    extends WFormField<List<T>> {
  WInfinityPickerFormField({
    Key? key,
    required WInfinityPickerFieldBuilder<T> builder,
    required Future<List<T>> Function(List<T> item) getData,
    required Future<bool> Function(List<T>) isLast,
    required this.field,
    Widget? title,
    this.onChanged,
    FormFieldSetter<List<T>>? onSaved,
    FormFieldValidator<List<T>>? validator,
    AutovalidateMode autovalidateMode = AutovalidateMode.disabled,
    bool enabled = true,
  }) : super(
          key: key,
          field: field,
          onSaved: onSaved,
          validator: validator,
          autovalidateMode: autovalidateMode,
          enabled: enabled,
          builder: (WFormFieldState<List<T>> fieldState) {
            final state = fieldState as _WInfinityPickerFormFieldState<T>;
            return WInfinityPickerField(
              title: title,
              isLast: isLast,
              value: state.value,
              getData: getData,
              builder: builder,
              onChanged: (value) => state.didChange(value as List<T>?),
            );
          },
        );

  ///直接使用[textField]进行builder
  WInfinityPickerFormField.textField({
    Key? key,
    required String Function(List<T> value) buildName,
    required Future<List<T>> Function(List<T> item) getData,
    required Future<bool> Function(List<T>) isLast,
    required this.field,
    Widget? title,
    this.onChanged,
    TextEditingController? controller,
    FormFieldSetter<List<T>>? onSaved,
    FormFieldValidator<List<T>>? validator,
    AutovalidateMode autovalidateMode = AutovalidateMode.disabled,
    bool enabled = true,
    FocusNode? focusNode,
    InputDecoration? decoration,
    TextInputType? keyboardType,
    TextCapitalization textCapitalization = TextCapitalization.none,
    TextInputAction? textInputAction,
    TextStyle? style,
    StrutStyle? strutStyle,
    TextDirection? textDirection,
    TextAlign textAlign = TextAlign.start,
    TextAlignVertical? textAlignVertical,
    bool autofocus = false,
    // bool readOnly = false,
    ToolbarOptions? toolbarOptions,
    bool? showCursor,
    String obscuringCharacter = '•',
    bool obscureText = false,
    bool autocorrect = true,
    SmartDashesType? smartDashesType,
    SmartQuotesType? smartQuotesType,
    bool enableSuggestions = true,
    MaxLengthEnforcement maxLengthEnforcement = MaxLengthEnforcement.enforced,
    int maxLines = 1,
    int? minLines,
    bool expands = false,
    int? maxLength,
    // GestureTapCallback onTap,
    VoidCallback? onEditingComplete,
    ValueChanged<String>? onFieldSubmitted,
    List<TextInputFormatter>? inputFormatters,
    double cursorWidth = 2.0,
    Radius? cursorRadius,
    Color? cursorColor,
    Brightness? keyboardAppearance,
    EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
    bool enableInteractiveSelection = true,
    InputCounterWidgetBuilder? buildCounter,
    ScrollPhysics? scrollPhysics,
    Iterable<String>? autofillHints,
  })  : 
        super(
          key: key,
          field: field,
          onSaved: onSaved,
          validator: validator,
          autovalidateMode: autovalidateMode,
          enabled: enabled,
          builder: (WFormFieldState<List<T>> fieldState) {
            final state = fieldState as _WInfinityPickerFormFieldState<T>;

            //主题
            InputDecoration _decoration = decoration ?? InputDecoration();
            _decoration = _decoration.applyDefaults(
              Theme.of(state.context).inputDecorationTheme,
            );
            _decoration = _decoration.copyWith(
              suffixIconConstraints:
                  _decoration.suffixIconConstraints ?? const BoxConstraints(),
              suffixIcon: _decoration.suffixIcon ??
                  Icon(
                    Icons.chevron_right,
                    color: Colors.black38,
                  ),
              errorText: state.errorText,
            );

            final _controller = controller ?? TextEditingController();

            _controller.value = _controller.value.copyWith(
              text: buildName(state.value ?? []),
            );
            return WInfinityPickerField(
              title: title,
              isLast: isLast,
              value: state.value,
              getData: getData,
              onChanged: (value) => state.didChange(value as List<T>?),
              builder: (value, trigger) {
                return TextField(
                  controller: _controller,
                  focusNode: focusNode,
                  decoration: _decoration,
                  keyboardType: keyboardType,
                  textInputAction: textInputAction,
                  style: style,
                  strutStyle: strutStyle,
                  textAlign: textAlign,
                  textAlignVertical: textAlignVertical,
                  textDirection: textDirection,
                  textCapitalization: textCapitalization,
                  autofocus: autofocus,
                  toolbarOptions: toolbarOptions,
                  readOnly: true,
                  showCursor: showCursor,
                  obscuringCharacter: obscuringCharacter,
                  obscureText: obscureText,
                  autocorrect: autocorrect,
                  smartDashesType: smartDashesType ??
                      (obscureText
                          ? SmartDashesType.disabled
                          : SmartDashesType.enabled),
                  smartQuotesType: smartQuotesType ??
                      (obscureText
                          ? SmartQuotesType.disabled
                          : SmartQuotesType.enabled),
                  enableSuggestions: enableSuggestions,
                  maxLengthEnforcement: maxLengthEnforcement,
                  maxLines: maxLines,
                  minLines: minLines,
                  expands: expands,
                  maxLength: maxLength,
                  // onChanged: onChangedHandler,
                  onTap: () => trigger(),
                  onEditingComplete: onEditingComplete,
                  onSubmitted: onFieldSubmitted,
                  inputFormatters: inputFormatters,
                  enabled: enabled,
                  cursorWidth: cursorWidth,
                  cursorRadius: cursorRadius,
                  cursorColor: cursorColor,
                  scrollPadding: scrollPadding,
                  scrollPhysics: scrollPhysics,
                  keyboardAppearance: keyboardAppearance,
                  enableInteractiveSelection: enableInteractiveSelection,
                  buildCounter: buildCounter,
                  autofillHints: autofillHints,
                );
              },
            );
          },
        );

  final String field;

  final WInfinityPickerFieldOnChanged<T>? onChanged;

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

class _WInfinityPickerFormFieldState<T extends WPickerEntity>
    extends WFormFieldState<List<T>> {
  @override
  WInfinityPickerFormField<T> get widget =>
      super.widget as WInfinityPickerFormField<T>;

  @override
  void didChange(List<T>? value) {
    super.didChange(value);
    if (widget.onChanged != null) {
      widget.onChanged!(value);
    }
  }
}
