// ignore_for_file: unnecessary_set_literal

import 'package:flutter/material.dart';
import 'package:wisdom_cli/src/assets.gen.dart';
import 'package:wisdom_cli/wisdom_cli.dart';

///Picker抽象类
///[WPicker],
///[WPickerUtil.infinity],
///[WPickerUtil.multiple],
///[WPickerUtil.single]中的[getData]返回的[List.item]类，应该要实现该抽象类
///
abstract class WPickerEntity {
  ///显示的名字
  String get selectName;

  ///唯一值
  Object get selectUnique;

  ///是否禁用
  bool get selectDisabled;
}

///
///通用快捷的构造[WPickerEntity],
///只需要传入一个[name],
///[unique]为次要的。不传也可以
class SinglePickerEntity implements WPickerEntity {
  final String? name;
  final Object? unique;
  final bool? disabled;
  final List? child;
  final List? cascade;

  SinglePickerEntity({
    this.name,
    this.unique,
    this.disabled = false,
    this.child,
    this.cascade,
  });

  @override
  String get selectName => name ?? '';

  @override
  Object get selectUnique => unique ?? '';

  @override
  bool get selectDisabled => disabled ?? false;

  List? get childList => child ?? [];

  List get cascadeList => cascade ?? [];

  ///Map快速构造[List<SinglePickerEntity>]
  ///
  ///```json
  ///{
  ///unique1:name1,
  ///unique2:name2,
  ///unique3:name3,
  ///unique4:name4,
  ///unique5:name5,
  ///unique6:name6,
  ///....
  ///}
  ///```
  static Future<List<SinglePickerEntity>> map2entity(
      Map<dynamic, String> data) async {
    final keys = data.keys;
    final list = keys
        .map((key) => SinglePickerEntity(name: data[key]!, unique: key))
        .toList();
    return list;
  }

  ///Map快速构造[List<SinglePickerEntity>]
  ///
  ///此构造方法[unique]也会使用[name],请确保数组无重复项
  ///```json
  ///[name1,name2,name3,...]
  ///```
  static Future<List<SinglePickerEntity>> list2entity(List<String> data) async {
    final list = data.map((e) => SinglePickerEntity(name: e)).toList();
    return list;
  }

  ///Map快速构造[List<SinglePickerEntity>]
  /// list<dynamic> to entity
  /// @data 列表数据
  /// @label 标题字段
  /// @value 值字段
  static Future<List<SinglePickerEntity>> listMap2entity(
      List<dynamic> data, label, value,
      {List? enableValue}) async {
    final list = data
        .map(
          (e) => SinglePickerEntity(
            name: e['$label'],
            unique: e['$value'],
            disabled: (enableValue != null && enableValue.length > 0)
                ? enableValue.contains(e['$value'])
                : false,
          ),
        )
        .toList();
    return list;
  }
}

///选择组件、非常基础。
///
///[getData]异步返回一个[List]，
///列表项[List.item]应该是一个[WPickerEntity]的实现类
///
///具体使用可参[底部弹出层封装]
///[WPickerUtil.single]、
///[WPickerUtil.multiple]、
///[WPickerUtil.infinity]
///
///
class WPicker<T extends WPickerEntity> extends StatefulWidget {
  WPicker({
    Key? key,
    this.getData,
    this.multiple = false,
    this.dense = false,
    this.initialValue = const [],
    this.listData,
    // this.enableValue = const [],
    this.onChanged,
    this.isSearch = false,
  })  : assert(multiple != null),
        assert(dense != null),
        assert(initialValue != null),
        assert(initialValue!.length <= 1 || multiple == true),
        super(key: key);

  ///是否多选
  final bool? multiple;
  final bool? dense;

  /// 是否可搜索
  final bool? isSearch;

  ///列表项[List.item]应该是一个[WPickerEntity]的实现类
  final WSinglePickerGetData<T>? getData;
  final List<T>? listData;

  ///为了单选多选的通用性，[initialValue]是一个List。
  ///当单选时,即[multiple==false],应满足[initialValue.length<=1]
  final List<T>? initialValue;
  // final List enableValue;

  ///选项发生改变时触发。
  ///[isTap==true]时，说明触发该函数的是由用户点击引起的，
  ///[isTap==false]时，说明触发该函数可能是由初始化，或其他组件内部原因引起的。
  final void Function(List<T>? value, bool isTap)? onChanged;

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

class _WPickerState<T extends WPickerEntity> extends State<WPicker<T>> {
  bool loading = false;

  List<T>? list = [];
  List<T>? initList = [];

  List<T>? value;
  void getData() async {
    if (widget.getData != null) {
      loading = true;
      try {
        initList = (await widget.getData!());
        list = initList;
      } finally {
        loading = false;
      }
      setState(() {});
    } else {
      loading = true;
      try {
        initList = widget.listData;
        list = initList;
      } finally {
        loading = false;
      }
      setState(() {});
    }
  }

  @override
  void initState() {
    super.initState();
    value = List.of(widget.initialValue ?? []);
    widget.onChanged!(value, false);
    getData();
  }

  ///是否已经选中？
  ///判断唯一值
  bool isSelected(T v) {
    return value!.indexWhere((e) => e.selectUnique == v.selectUnique) != -1;
  }

  ///点击事件
  ///会触发widget.onChanged(selects, true);
  void ontap(T v) {
    if (!(v.selectDisabled)) {
      if (!widget.multiple!) {
        value = [v];
      } else {
        final exit = isSelected(v);
        if (exit) {
          value!.removeWhere((e) => e.selectUnique == v.selectUnique);
        } else {
          value!.add(v);
        }
      }
      setState(() {});
      if (widget.onChanged != null) {
        widget.onChanged!(value, true);
      }
    }
  }

  void onInput(v) {
    List cList =
        (initList!.map((e) => e.selectName.contains(v) ? e : null)).toList();
    List<T> tempList = [];
    cList.forEach((element) {
      if (element != null) {
        tempList.add(element);
      }
    });
    list = tempList;
    setState(() {});
  }

  /// 为解决flutter截断不完整
  String breakWord(String text) {
    if (text.isEmpty) {
      return text;
    }
    String breakWord = ' ';
    text.runes.forEach((element) {
      breakWord += String.fromCharCode(element);
      breakWord += '\u200B';
    });
    return breakWord;
  }

  @override
  Widget build(BuildContext context) {
    if (loading) return Center(child: WLoading());
    final colorScheme = WTheme.of(context).colorScheme;
    return Stack(
      children: [
        if (list == null || list!.length == 0 || list?.isEmpty == true) ...[
          WEmptyWidget(
            margin: EdgeInsets.only(
              top: widget.isSearch == true ? 59.pt : 15.pt,
            ),
            text: WisText('暂无数据'),
          ),
        ] else ...[
          ListView(
            padding: EdgeInsets.only(
              top: widget.isSearch == true ? 49.pt : 0,
            ),
            children: list!.map(
              (value) {
                return Wisdom(
                  width: MediaQuery.of(context).size.width,
                  margin: EdgeInsets.symmetric(horizontal: 15.pt),
                  border: Border(bottom: Divider.createBorderSide(context)),
                  child: ListTile(
                    onTap: () => ontap(value),
                    dense: widget.dense,
                    contentPadding: EdgeInsets.zero,
                    selected: isSelected(value),
                    enabled: !(value.selectDisabled),
                    title: Wisdom.row(
                      width: MediaQuery.of(context).size.width,
                      // mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        // 增加勾选按钮样式
                        if (isSelected(value)) ...[
                          Wisdom(
                            padding: EdgeInsets.only(right: 10.pt),
                            child: widget.multiple == true
                                ? Image(
                                    image: AssetList.$fxxz_png_image,
                                    height: 16.pt)
                                : Image(
                                    image: AssetList.$danxuan_png_image,
                                    height: 16.pt),
                          ),
                           WisText(
                          '${breakWord(value.selectName)}',
                          color: colorScheme.primary,
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                        ).asExpanded(),
                        ] else ...[
                          Wisdom(
                            padding: EdgeInsets.only(right: 10.pt),
                            child: widget.multiple == true
                                ? Image(
                                    image: AssetList.$dx_png_image,
                                    height: 16.pt)
                                : Image(
                                    image: AssetList.$danxuanyuan_png_image,
                                    height: 16.pt),
                          ),
                           WisText(
                          '${breakWord(value.selectName)}',
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                        ).asExpanded(),
                        ],
                       
                      ],
                    ),
                  ),
                );
              },
            ).toList(),
          ),
        ],
        if (widget.isSearch == true) ...[
          Positioned(
            top: 0,
            left: 0,
            right: 0,
            child: WSearch(
              hintText: '输入关键词搜索',
              onSubmitted: (v) => onInput(v),
              onCancel: () => onInput(''),
              onChanged: (v) => onInput(v),
              moonlight: false,
              padding: EdgeInsets.symmetric(vertical: 10.pt),
              isDark: true,
              backColor: Colors.white,
            ),
          ),
        ],
      ],
    );
  }
}

class WTreePicker<T extends WPickerEntity> extends StatefulWidget {
  WTreePicker({
    Key? key,
    required this.data,
    required this.labelname,
    required this.valuename,
    required this.childname,
    required this.firstName,
    required this.firstValue,
    this.multiple = false,
    this.dense = false,
    this.initialValue = const [],
    // this.enableValue = const [],

    this.onChanged,
    this.isSearch = false,
  }) : super(key: key);
  final String? labelname;
  final String? valuename;
  final String? childname;
  final String? firstName;
  final String? firstValue;

  ///是否多选
  final bool? multiple;
  final bool? dense;

  /// 是否可搜索
  final bool? isSearch;

  ///列表项[List.item]应该是一个[WPickerEntity]的实现类
  final List? data;

  ///为了单选多选的通用性，[initialValue]是一个List。
  ///当单选时,即[multiple==false],应满足[initialValue.length<=1]
  final List? initialValue;
  // final List enableValue;

  ///选项发生改变时触发。
  ///[isTap==true]时，说明触发该函数的是由用户点击引起的，
  ///[isTap==false]时，说明触发该函数可能是由初始化，或其他组件内部原因引起的。
  final void Function(List value, bool isTap)? onChanged;

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

class _WTreePickerState<T extends WPickerEntity> extends State<WTreePicker<T>> {
  bool? loading = false;

  List? list = [];
  var _fistValue;
  List? initList = [];
  List? secondList = [];
  String? _searchValue;

  List? value;
  void getData() async {
    if (widget.data != null) {
      loading = true;
      try {
        initList = widget.data;
        list = initList!;
        _fistValue = initList!.length > 0 ? initList![0] : null;
        secondList = _fistValue[widget.childname] ?? [];
      } finally {
        loading = false;
      }
      setState(() {});
    }
  }

  @override
  void initState() {
    super.initState();
    value = List.of(widget.initialValue ?? []);
    getData();
  }

  ///是否已经选中？
  ///判断唯一值
  bool isSelected(v) {
    return value!
            .indexWhere((e) => e[widget.valuename] == v[widget.valuename]) !=
        -1;
  }

  ///点击事件
  ///会触发widget.onChanged(selects, true);
  void ontap(v) {
    // if (!(v?.selectDisabled ?? false)) {
    if (widget.multiple == false) {
      value = [v];
    } else {
      final exit = isSelected(v);
      if (exit) {
        value!.removeWhere((e) => e[widget.valuename] == v[widget.valuename]);
      } else {
        value!.add(v);
      }
    }
    setState(() {});
    if (widget.onChanged != null) {
      widget.onChanged!(value!, true);
    }
  }

  onSelectFirst(v) {
    _fistValue = v;
    secondList = _fistValue[widget.childname] ?? [];
    setState(() {});
  }

  void onInput(v) {
    _searchValue = v;
    if (v == null || v == '') {
      list = initList!;
    } else {
      List tempList = [];
      initList!.forEach((ele) => {
            ele[widget.childname].forEach((item) => {
                  if (item[widget.labelname].contains(v))
                    {
                      tempList.add(item),
                    }
                }),
          });
      list = tempList;
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    final colorScheme = WTheme.of(context).colorScheme;
    if (loading == true) return Center(child: WLoading());
    return Stack(
      children: [
        Wisdom.row(
          color: Colors.white,
          mainAxisSize: MainAxisSize.min,
          children: [
            if (_searchValue != null && _searchValue != '') ...[
              if (list == null || list!.length == 0) ...[
                Wisdom(
                  width: MediaQuery.of(context).size.width,
                  padding: EdgeInsets.only(
                    top: widget.isSearch == true ? 49.pt : 0,
                  ),
                  child: Center(
                    child: WEmptyWidget(
                      text: WisText('搜索不到，空空如也~'),
                    ),
                  ),
                ),
              ] else ...[
                SizedBox(
                  height: double.infinity,
                  width: MediaQuery.of(context).size.width,
                  child: ListView(
                    padding: EdgeInsets.only(
                      top: widget.isSearch == true ? 49.pt : 0,
                    ),
                    children: list!.map(
                      (value) {
                        return Wisdom(
                          margin: EdgeInsets.symmetric(horizontal: 15.pt),
                          border:
                              Border(bottom: Divider.createBorderSide(context)),
                          child: ListTile(
                            onTap: () => ontap(value),
                            dense: widget.dense,
                            contentPadding: EdgeInsets.zero,
                            selected: false,
                            enabled: true,
                            title: Row(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: [
                                WisText(
                                  '${value[widget.labelname] ?? '--'}',
                                  maxLines: 1,
                                  overflow: TextOverflow.ellipsis,
                                ).asExpanded(),
                                // 增加勾选按钮样式
                                if (isSelected(value)) ...[
                                  Wisdom(
                                    padding: EdgeInsets.only(left: 10.pt),
                                    child: Image(
                                      image: AssetList.$xzh_png_image,
                                      height: 10.pt,
                                    ),
                                  ),
                                ],
                              ],
                            ),
                          ),
                        );
                      },
                    ).toList(),
                  ),
                ).asExpanded(),
              ]
            ] else ...[
              if (list != null && list!.length > 0) ...[
                SizedBox(
                  height: double.infinity,
                  width: 130.pt,
                  child: ListView(
                    padding: EdgeInsets.only(
                      top: widget.isSearch == true ? 49.pt : 0,
                    ),
                    children: list!.map(
                      (value) {
                        return Wisdom(
                          margin: EdgeInsets.symmetric(horizontal: 15.pt),
                          border:
                              Border(bottom: Divider.createBorderSide(context)),
                          child: ListTile(
                            onTap: () => onSelectFirst(value),
                            dense: widget.dense,
                            contentPadding: EdgeInsets.zero,
                            selected: _fistValue != null &&
                                _fistValue[widget.firstValue] ==
                                    value[widget.firstValue],
                            enabled: true,
                            title: Row(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: [
                                if (_fistValue != null &&
                                    _fistValue[widget.firstValue] ==
                                        value[widget.firstValue]) ...[
                                  Wisdom(
                                    color: colorScheme.primary,
                                    height: 14.pt,
                                    width: 2.pt,
                                    margin: EdgeInsets.only(right: 5.pt),
                                  ),
                                ],
                                WisText(
                                  '${value[widget.firstName] ?? '--'}',
                                  maxLines: 1,
                                  color: _fistValue != null &&
                                          _fistValue[widget.firstValue] ==
                                              value[widget.firstValue]
                                      ? colorScheme.primary
                                      : null,
                                  overflow: TextOverflow.ellipsis,
                                ).asExpanded(),
                              ],
                            ),
                          ),
                        );
                      },
                    ).toList(),
                  ),
                ),
                if (secondList != null && secondList!.length > 0) ...[
                  SizedBox(
                    height: double.infinity,
                    width: MediaQuery.of(context).size.width - 130.pt,
                    child: ListView(
                      padding: EdgeInsets.only(
                        top: widget.isSearch == true ? 49.pt : 0,
                      ),
                      children: secondList!.map(
                        (value) {
                          return Wisdom(
                            margin: EdgeInsets.only(right: 15.pt),
                            border: Border(
                                bottom: Divider.createBorderSide(context)),
                            child: ListTile(
                              onTap: () => ontap(value),
                              dense: widget.dense,
                              contentPadding: EdgeInsets.zero,
                              selected: false,
                              enabled: true,
                              title: Row(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceBetween,
                                children: [
                                  WisText(
                                    '${value[widget.labelname] ?? '--'}',
                                    maxLines: 1,
                                    overflow: TextOverflow.ellipsis,
                                  ).asExpanded(),
                                  // 增加勾选按钮样式
                                  if (isSelected(value)) ...[
                                    Wisdom(
                                      padding: EdgeInsets.only(left: 10.pt),
                                      child: Image(
                                        image: AssetList.$xzh_png_image,
                                        height: 10.pt,
                                      ),
                                    ),
                                  ],
                                ],
                              ),
                            ),
                          );
                        },
                      ).toList(),
                    ),
                  )
                ] else ...[
                  Wisdom(
                    width: MediaQuery.of(context).size.width - 130.pt,
                    padding: EdgeInsets.only(
                      top: widget.isSearch == true ? 49.pt : 0,
                    ),
                    child: Center(
                      child: WEmptyWidget(
                        text: WisText('暂无数据'),
                      ),
                    ),
                  ),
                ]
              ] else ...[
                Wisdom(
                  width: MediaQuery.of(context).size.width,
                  padding: EdgeInsets.only(
                    top: widget.isSearch == true ? 49.pt : 0,
                  ),
                  child: Center(
                    child: WEmptyWidget(
                      text: WisText('暂无数据'),
                    ),
                  ),
                ),
              ]
            ]
          ],
        ),
        if (widget.isSearch == true) ...[
          Positioned(
            top: 0,
            left: 0,
            right: 0,
            child: WSearch(
              onCancel: () => onInput(null),
              hintText: '输入关键词搜索',
              onSubmitted: (v) => onInput(v),
              onChanged: (v) => onInput(v),
              moonlight: false,
              padding: EdgeInsets.symmetric(vertical: 10.pt),
              isDark: true,
              backColor: Colors.white,
            ),
          ),
        ],
      ],
    );
  }
}
