// ignore_for_file: public_member_api_docs, sort_constructors_first
// ignore_for_file: invalid_use_of_visible_for_testing_member

import 'dart:convert';
import 'dart:developer';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:dotted_border/dotted_border.dart';
import 'package:ebroker/exports/main_export.dart';
import 'package:ebroker/utils/Extensions/extensions.dart';
import 'package:ebroker/utils/helper_utils.dart';
import 'package:ebroker/utils/responsiveSize.dart';
import 'package:ebroker/utils/ui_utils.dart';
import 'package:file_icon/src/data.dart' as d;
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';

import '../../../../utils/AppIcon.dart';
import '../custom_text_form_field.dart';

/// Note: Here i have used abstract factory pattern and builder pattern
/// You can learn design patterns from internet
/// so don't be confuse
List kDoNotReBuildThese = [];
List kDoNotReBuildDropdown = [];

abstract class AbstractField {
  final BuildContext context;
  static Map fieldsData = {};
  AbstractField(this.context);
  Widget createField(Map parameters);
}

class AbstractTextField extends AbstractField {
  AbstractTextField(BuildContext context)
      : super(
          context,
        );
  // TextEditingController? _controller;

  ///Here Builder pattern to set values,
  /// because when if we get it from constructor it will be messed in Factory class so it

  ///You can uncomment it if you want to use controller out side of the class

  // AbstractTextField setController(TextEditingController controller) {
  //   _controller = controller;
  //   return this;
  // }

  @override
  Widget createField(parameters) {
    return Column(
      children: [
        Row(
          children: [
            Container(
              width: 48.rw(context),
              height: 48.rh(context),
              decoration: BoxDecoration(
                color: context.color.tertiaryColor.withOpacity(0.1),
                borderRadius: BorderRadius.circular(10),
              ),
              child: Container(
                height: 24,
                width: 24,
                child: FittedBox(
                  fit: BoxFit.none,
                  child: UiUtils.imageType(parameters['image'],
                      color: Constant.adaptThemeColorSvg
                          ? context.color.tertiaryColor
                          : null,
                      width: 24,
                      height: 24,
                      fit: BoxFit.cover),
                ),
              ),
            ),
            SizedBox(
              width: 10.rw(context),
            ),
            Text(parameters['name'])
                .size(context.font.large)
                .bold(weight: FontWeight.w500)
                .color(context.color.textColorDark)
          ],
        ),
        SizedBox(
          height: 14.rh(context),
        ),
        CustomTextFieldDynamic(
          action: TextInputAction.next,
          initController: parameters['value'] != null ? true : false,
          value: parameters['value'].toString(),
          hintText: "writeSomething".translate(context),
          id: parameters['id'],
        )
      ],
    );
  }
}

class AbstractTextAreaField extends AbstractField {
  AbstractTextAreaField(BuildContext context)
      : super(
          context,
        );
  // TextEditingController? _controller;

  ///   Here Builder pattern to set values,
  ///   because when if we get it from constructor it will be messed in Factory class so it
  ///   You can uncomment it if you want to use controller out side of class
  //AbstractTextAreaField setController(TextEditingController controller) {
  //  // _controller = controller;
  //  return this;
  //}

  @override
  Widget createField(parameters) {
    return Padding(
      padding: const EdgeInsets.symmetric(
        vertical: .0,
      ),
      child: Column(
        children: [
          Row(
            children: [
              Container(
                width: 48.rw(context),
                height: 48.rh(context),
                decoration: BoxDecoration(
                  color: context.color.tertiaryColor.withOpacity(0.1),
                  borderRadius: BorderRadius.circular(10),
                ),
                child: Container(
                  height: 24,
                  width: 24,
                  child: FittedBox(
                    fit: BoxFit.none,
                    child: UiUtils.imageType(parameters['image'],
                        color: Constant.adaptThemeColorSvg
                            ? context.color.tertiaryColor
                            : null,
                        width: 24,
                        height: 24,
                        fit: BoxFit.cover),
                  ),
                ),
              ),
              SizedBox(
                width: 10.rw(context),
              ),
              Text(parameters['name'])
                  .size(context.font.large)
                  .color(
                    context.color.textColorDark,
                  )
                  .bold(weight: FontWeight.w500)
            ],
          ),
          SizedBox(
            height: 14.rh(context),
          ),
          CustomTextFormField(
            hintText: "Write something...",
            minLine: 4,
            maxLine: 100,
            validator: CustomTextFieldValidator.maxFifty,
            controller: parameters['value'] != null
                ? TextEditingController(text: parameters['value'].toString())
                : null,
            onChange: (value) {
              AbstractField.fieldsData.addAll({parameters['id']: value});
            },
          )
        ],
      ),
    );

    // return TextFormField(
    //   maxLines: null,
    //   minLines: 5,
    //   onChanged: (value) {
    //     AbstractField.fieldsData.addAll({parameters['id']: value});
    //   },
    //   decoration: InputDecoration(hintText: parameters['name']),
    // );
  }
}

class AbstractNumberField extends AbstractField {
  AbstractNumberField(BuildContext context)
      : super(
          context,
        );
  // TextEditingController? _controller;

  ///Here, Builder pattern to set values,
  /// because when if we get it from constructor it will be messed in Factory class so it

  ///You can uncomment it if you want to use controller out side of class
  // AbstractNumberField setController(TextEditingController controller) {
  //   _controller = controller;
  //   return this;
  // }

  @override
  Widget createField(parameters) {
    return Padding(
        padding: const EdgeInsets.symmetric(vertical: 0.0),
        child: Column(
          children: [
            Row(
              children: [
                Container(
                  width: 48.rw(context),
                  height: 48.rh(context),
                  decoration: BoxDecoration(
                    color: context.color.tertiaryColor.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: SizedBox(
                    height: 24,
                    width: 24,
                    child: FittedBox(
                      fit: BoxFit.none,
                      child: UiUtils.imageType(parameters['image'],
                          color: Constant.adaptThemeColorSvg
                              ? context.color.tertiaryColor
                              : null,
                          width: 24,
                          height: 24,
                          fit: BoxFit.cover),
                    ),
                  ),
                ),
                SizedBox(
                  width: 10.rw(context),
                ),
                Text(parameters['name'])
                    .size(context.font.large)
                    .bold(weight: FontWeight.w500)
                    .color(context.color.textColorDark)
              ],
            ),
            SizedBox(
              height: 14.rh(context),
            ),
            CustomTextFieldDynamic(
              initController: parameters['value'] != null ? true : false,
              value: parameters['value'].toString(),
              hintText: "addNumerical".translate(context),
              formaters: [
                FilteringTextInputFormatter.allow(
                  RegExp("[0-9]"),
                ),
              ],
              action: TextInputAction.next,
              keyboardType: TextInputType.number,
              id: parameters['id'],
            ),
          ],
        ));
  }
}

class AbstractDropdown extends AbstractField {
  Function(dynamic onData)? _onChange;
  List kDropdownSelected = [];
  UniqueKey _key = UniqueKey();
  List? _items;
  dynamic selectedItem;
  AbstractDropdown(
    BuildContext context,
  ) : super(context);

  ///We can say it method chaining
  ///Here this is builder pattern used here it will return it self after assign value so new class has already assigned value
  AbstractDropdown setOnChange(Function(dynamic onChange) onChange) {
    _onChange = onChange;
    return this;
  }

  AbstractDropdown setItems(List items) {
    _items = items;
    return this;
  }

  AbstractDropdown setSelectedItem(dynamic item) {
    if (item != null) {
      if (!kDoNotReBuildDropdown.contains(_key)) {
        kDoNotReBuildDropdown.add(_key);
        dropDownItemChange.value = item;
      }
    }

    return this;
  }

  late ValueNotifier<String> dropDownItemChange =
      ValueNotifier<String>(_items?.first);

  @override
  Widget createField(parameters) {
    return CustomDropdownState(
      key: _key,
      dropDownItemChange: dropDownItemChange,
      parameters: parameters,
      items: _items ?? [],
    );

    return ValueListenableBuilder(
        valueListenable: dropDownItemChange,
        builder: (context, value, child) {
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Container(
                    width: 48.rw(context),
                    height: 48.rh(context),
                    decoration: BoxDecoration(
                      color: context.color.tertiaryColor.withOpacity(
                        0.1,
                      ),
                      borderRadius: BorderRadius.circular(
                        10,
                      ),
                    ),
                    child: UiUtils.imageType(parameters['image'],
                        fit: BoxFit.none),
                  ),
                  SizedBox(
                    width: 10.rw(
                      context,
                    ),
                  ),
                  Text(
                    parameters['name'],
                  )
                      .size(
                        context.font.large,
                      )
                      .color(
                        context.color.textColorDark,
                      )
                ],
              ),
              SizedBox(
                height: 10.rh(context),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(
                  horizontal: 3,
                ),
                child: Container(
                  decoration: BoxDecoration(
                      color: context.color.secondaryColor,
                      borderRadius: BorderRadius.circular(
                        10,
                      ),
                      border: Border.all(
                        width: 1.5,
                        color: context.color.borderColor,
                      )),
                  child: Padding(
                    padding: const EdgeInsets.all(
                      8.0,
                    ),
                    child: SizedBox(
                      width: double.infinity,
                      child: DropdownButton(
                        value: value,
                        isExpanded: true,
                        padding: EdgeInsets.symmetric(vertical: 5),
                        icon: SvgPicture.asset(AppIcons.downArrow),
                        isDense: true,
                        borderRadius: BorderRadius.circular(
                          10,
                        ),
                        underline: const SizedBox.shrink(),
                        items: _items
                            ?.map((e) => DropdownMenuItem(
                                  value: e,
                                  child: Text(
                                    e,
                                  ),
                                ))
                            .toList(),
                        onChanged: (dynamic v) {
                          dropDownItemChange.value = v;
                          AbstractField.fieldsData.addAll(
                            {
                              parameters['id']: v,
                            },
                          );

                          _onChange?.call(v);
                        },
                      ),
                    ),
                  ),
                ),
              ),
              SizedBox(
                height: 10.rh(
                  context,
                ),
              )
            ],
          );
        });
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is AbstractDropdown &&
          runtimeType == other.runtimeType &&
          _onChange == other._onChange &&
          kDropdownSelected == other.kDropdownSelected &&
          _key == other._key &&
          _items == other._items &&
          selectedItem == other.selectedItem &&
          dropDownItemChange == other.dropDownItemChange;

  @override
  int get hashCode =>
      _onChange.hashCode ^
      kDropdownSelected.hashCode ^
      _key.hashCode ^
      _items.hashCode ^
      selectedItem.hashCode ^
      dropDownItemChange.hashCode;
}

class AbstractRadioButton extends AbstractField {
  AbstractRadioButton(BuildContext context) : super(context);
  List? _radioValues;
  // late ValueNotifier selectedRadio;

  AbstractRadioButton setValues(
    List values,
  ) {
    _radioValues = values;
    // selectedRadio = ValueNotifier(_radioValues?.first);
    return this;
  }

  @override
  Widget createField(parameters) {
    return CustomRadioButtonWidget(
      parameters: parameters,
      radioValues: _radioValues,
    );
    // return ValueListenableBuilder(
    //     valueListenable: selectedRadio,
    //     builder: (context, value, child) {
    //       return Column(
    //         crossAxisAlignment: CrossAxisAlignment.start,
    //         children: [
    //           Row(
    //             children: [
    //               Container(
    //                 width: 48.rw(context),
    //                 height: 48.rh(context),
    //                 decoration: BoxDecoration(
    //                   color: context.color.teritoryColor.withOpacity(0.1),
    //                   borderRadius: BorderRadius.circular(10),
    //                 ),
    //                 child: UiUtils.imageType(parameters['image'],
    //                     fit: BoxFit.none),
    //               ),
    //               SizedBox(
    //                 width: 10.rw(context),
    //               ),
    //               Text(parameters['name'])
    //                   .size(context.font.large)
    //                   .color(context.color.textColorDark)
    //             ],
    //           ),
    //           SizedBox(
    //             height: 10.rh(context),
    //           ),
    //           Wrap(
    //               alignment: WrapAlignment.start,
    //               runAlignment: WrapAlignment.start,
    //               crossAxisAlignment: WrapCrossAlignment.start,
    //               children: List.generate(
    //                   _radioValues?.length ?? 0,
    //                   (index) => Row(
    //                         mainAxisSize: MainAxisSize.min,
    //                         children: [
    //                           Radio(
    //                             value: _radioValues?[index],
    //                             groupValue: value,
    //                             fillColor: MaterialStatePropertyAll(
    //                                 context.color.teritoryColor),
    //                             onChanged: (dynamic e) {
    //                               selectedRadio.value = e;
    //                               AbstractField.fieldsData
    //                                   .addAll({parameters['id']: e});
    //                             },
    //                           ),
    //                           Text(_radioValues?[index])
    //                         ],
    //                       )))
    //         ],
    //       );

    //       // return Column(
    //       //   crossAxisAlignment: CrossAxisAlignment.start,
    //       //   children: [
    //       //     Text(parameters['name']),
    //       //     Wrap(
    //       //       children: _radioValues
    //       //               ?.map((item) {
    //       //                 return Row(
    //       //                   mainAxisSize: MainAxisSize.min,
    //       //                   children: [
    //       //                     Text(item),
    //       //                     Radio(
    //       //                         value: item,
    //       //                         groupValue: value,
    //       //                         onChanged: (dynamic e) {
    //       //                           selectedRadio.value = e;
    //       //                           AbstractField.fieldsData
    //       //                               .addAll({parameters['id']: e});
    //       //                         }),
    //       //                   ],
    //       //                 );
    //       //               })
    //       //               .toList()
    //       //               .cast() ??
    //       //           [],
    //       //     ),
    //       //   ],
    //       // );
    //     });
  }
}

class AbstractCheckBoxButton extends AbstractField {
  AbstractCheckBoxButton(BuildContext context) : super(context);

  List? _checkValues;

  bool initComplete = false;
  AbstractCheckBoxButton setCheckBoxValues(List values) {
    _checkValues = values;
    return this;
  }

  @override
  Widget createField(parameters) {
    log(_checkValues.toString(), name: "##Rfmdfksa");
    return CustomCheckBox(
      parameters: parameters,
      checkValues: _checkValues,
      index: 0,
      initComplete: true,
    );
  }

  void dispose() {
    // checked.dispose();
  }
}

class AbstractPickFileButton extends AbstractField {
  AbstractPickFileButton(BuildContext context) : super(context);
  ValueNotifier filePicked = ValueNotifier(false);
  ValueNotifier<String?> picked = ValueNotifier(null);
  Future<File?> pickFile() async {
    FilePickerResult? picker = await FilePicker.platform.pickFiles();
    if (picker != null) {
      filePicked.value = true;
      File file = File(
        picker.files.single.path!,
      );
      picked.value = file.path;
      return file;
    }
    filePicked.value = false;
    picked.value = null;
    return null;
  }

  @override
  Widget createField(parameters) {
    picked.value = parameters['value'];

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Container(
              width: 48.rw(context),
              height: 48.rh(context),
              decoration: BoxDecoration(
                color: context.color.tertiaryColor.withOpacity(0.1),
                borderRadius: BorderRadius.circular(10),
              ),
              child: Container(
                height: 24,
                width: 24,
                child: FittedBox(
                  fit: BoxFit.none,
                  child: UiUtils.imageType(parameters['image'],
                      color: Constant.adaptThemeColorSvg
                          ? context.color.tertiaryColor
                          : null,
                      width: 24,
                      height: 24,
                      fit: BoxFit.cover),
                ),
              ),
            ),
            SizedBox(
              width: 10.rw(context),
            ),
            Text(parameters['name'])
                .size(context.font.large)
                .bold(weight: FontWeight.w500)
                .color(context.color.textColorDark),
          ],
        ),
        SizedBox(
          height: 14.rh(context),
        ),
        GestureDetector(
          onTap: () async {
            File? file = await pickFile();
            if (file != null) {
              MultipartFile multipartFile =
                  await MultipartFile.fromFile(file.path);

              /// Add data to static Map
              AbstractField.fieldsData
                  .addAll({parameters['id']: multipartFile});
            }
          },
          child: DottedBorder(
              borderType: BorderType.RRect,
              radius: const Radius.circular(10),
              color: context.color.textLightColor,
              strokeCap: StrokeCap.round,
              padding: const EdgeInsets.all(5),
              dashPattern: const [3, 3],
              child: Container(
                width: double.infinity,
                height: 43,
                decoration:
                    BoxDecoration(borderRadius: BorderRadius.circular(10)),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Icon(Icons.add),
                    const SizedBox(
                      width: 5,
                    ),
                    const Text("Add File")
                        .color(context.color.textLightColor)
                        .size(context.font.large)
                  ],
                ),
              )),
        ),
        ValueListenableBuilder(
            valueListenable: picked,
            builder: (context, String? pickedFilePath, c) {
              if (pickedFilePath == null) {
                return const SizedBox.shrink();
              }
              return Container(
                child: Row(
                  children: [
                    Icon(
                      IconData(
                        d.iconSetMap[".${pickedFilePath.split(".").last}"]!
                            .codePoint,
                        fontFamily: 'Seti',
                        fontPackage: 'file_icon',
                      ),
                      color: context.color.tertiaryColor,
                      size: 35,
                    ),
                    const SizedBox(
                      width: 5,
                    ),
                    Expanded(
                        flex: 2,
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(pickedFilePath.split("/").last)
                                .setMaxLines(lines: 1)
                                .bold(weight: FontWeight.w500),
                            if (!(pickedFilePath.startsWith("http") ||
                                pickedFilePath.startsWith("https")))
                              Text(HelperUtils.getFileSizeString(
                                bytes: File(pickedFilePath).lengthSync(),
                              ).toUpperCase())
                                  .size(context.font.smaller)
                          ],
                        )),
                    const Spacer(flex: 1),
                    IconButton(
                        onPressed: () {
                          AbstractField.fieldsData.remove(parameters['id']);

                          picked.value = null;
                        },
                        icon: Icon(Icons.close))
                  ],
                ),
              );
            })
      ],
    );

    // return MaterialButton(
    //   onPressed: () async {
    //     File? file = await pickFile();
    //     if (file != null) {
    //       MultipartFile multipartFile = await MultipartFile.fromFile(file.path);

    //       /// Add data to static Map
    //       AbstractField.fieldsData.addAll({parameters['id']: multipartFile});
    //     }
    //   },
    //   color: Colors.grey.shade200,
    //   child: const Text("Pick"),
    // );
  }
}

///Factory class which will return class according to type
class FieldFactory {
  static AbstractField getField(BuildContext context, String fieldType) {
    if (fieldType == 'textbox') {
      return AbstractTextField(context);
    } else if (fieldType == 'dropdown') {
      return AbstractDropdown(context);
    } else if (fieldType == 'radiobutton') {
      return AbstractRadioButton(context);
    } else if (fieldType == 'number') {
      return AbstractNumberField(
        context,
      );
    } else if (fieldType == "checkbox") {
      return AbstractCheckBoxButton(context);
    } else if (fieldType == "textarea") {
      return AbstractTextAreaField(context);
    } else if (fieldType == "file") {
      return AbstractPickFileButton(context);
    }
    throw Exception('Invalid field type: $fieldType');
  }
}

class CustomRadioButtonWidget extends StatefulWidget {
  final dynamic parameters;
  final dynamic radioValues;
  const CustomRadioButtonWidget({super.key, this.parameters, this.radioValues});

  @override
  State<CustomRadioButtonWidget> createState() =>
      _CustomRadioButtonWidgetState();
}

class _CustomRadioButtonWidgetState extends State<CustomRadioButtonWidget> {
  late ValueNotifier selectedRadio;
  bool isInitialized = false;
  @override
  void initState() {
    selectedRadio = ValueNotifier(widget.radioValues?.first);

    if (widget.parameters['value'] != null && isInitialized == false) {
      selectedRadio.value = widget.parameters['value'];
      isInitialized = true;
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
        valueListenable: selectedRadio,
        builder: (context, value, child) {
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Container(
                    width: 48.rw(context),
                    height: 48.rh(context),
                    decoration: BoxDecoration(
                      color: context.color.tertiaryColor.withOpacity(0.1),
                      borderRadius: BorderRadius.circular(10),
                    ),
                    child: Container(
                      height: 24,
                      width: 24,
                      child: FittedBox(
                        fit: BoxFit.none,
                        child: UiUtils.imageType(widget.parameters['image'],
                            color: Constant.adaptThemeColorSvg
                                ? context.color.tertiaryColor
                                : null,
                            width: 24,
                            height: 24,
                            fit: BoxFit.cover),
                      ),
                    ),
                  ),
                  SizedBox(
                    width: 10.rw(context),
                  ),
                  Text(widget.parameters['name'])
                      .size(context.font.large)
                      .bold(weight: FontWeight.w500)
                      .color(context.color.textColorDark)
                ],
              ),
              SizedBox(
                height: 14.rh(context),
              ),
              Wrap(
                  alignment: WrapAlignment.start,
                  runAlignment: WrapAlignment.start,
                  crossAxisAlignment: WrapCrossAlignment.start,
                  children:
                      List.generate(widget.radioValues?.length ?? 0, (index) {
                    return Padding(
                      padding: EdgeInsetsDirectional.only(
                        start: index == 0 ? 0 : 4,
                        end: 4,
                        bottom: 4,
                        top: 4,
                      ),
                      child: InkWell(
                        borderRadius: BorderRadius.circular(10),
                        onTap: () {
                          selectedRadio.value = widget.radioValues?[index];
                          AbstractField.fieldsData.addAll({
                            widget.parameters['id']: widget.radioValues?[index]
                          });
                        },
                        child: Container(
                          decoration: BoxDecoration(
                              border: Border.all(
                                  color: context.color.borderColor, width: 1.5),
                              color: selectedRadio.value ==
                                      widget.radioValues?[index]
                                  ? context.color.tertiaryColor.withOpacity(0.1)
                                  : context.color.secondaryColor,
                              borderRadius: BorderRadius.circular(10)),
                          child: Padding(
                              padding: const EdgeInsets.symmetric(
                                  vertical: 10, horizontal: 15),
                              child: Text(widget.radioValues?[index]).color(
                                  selectedRadio.value ==
                                          widget.radioValues?[index]
                                      ? context.color.tertiaryColor
                                      : context.color.textLightColor)),
                        ),
                      ),
                    );

                    return Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Radio(
                          value: widget.radioValues?[index],
                          groupValue: value,
                          fillColor: MaterialStatePropertyAll(
                              context.color.tertiaryColor),
                          onChanged: (dynamic e) {
                            selectedRadio.value = e;
                            AbstractField.fieldsData
                                .addAll({widget.parameters['id']: e});
                          },
                        ),
                        Text(widget.radioValues?[index])
                      ],
                    );
                  }))
            ],
          );

          // return Column(
          //   crossAxisAlignment: CrossAxisAlignment.start,
          //   children: [
          //     Text(parameters['name']),
          //     Wrap(
          //       children: _radioValues
          //               ?.map((item) {
          //                 return Row(
          //                   mainAxisSize: MainAxisSize.min,
          //                   children: [
          //                     Text(item),
          //                     Radio(
          //                         value: item,
          //                         groupValue: value,
          //                         onChanged: (dynamic e) {
          //                           selectedRadio.value = e;
          //                           AbstractField.fieldsData
          //                               .addAll({parameters['id']: e});
          //                         }),
          //                   ],
          //                 );
          //               })
          //               .toList()
          //               .cast() ??
          //           [],
          //     ),
          //   ],
          // );
        });
  }
}

class CustomCheckBox extends StatefulWidget {
  final dynamic parameters;
  final dynamic checkValues;
  final dynamic initComplete;
  final dynamic index;
  const CustomCheckBox(
      {super.key,
      this.parameters,
      this.checkValues,
      this.initComplete,
      this.index});

  @override
  State<CustomCheckBox> createState() => _CustomCheckBoxState();
}

class _CustomCheckBoxState extends State<CustomCheckBox> {
  final ValueNotifier<List> checked = ValueNotifier([]);
  @override
  void initState() {
    // log("VA ${widget.parameters}");
    if (widget.parameters.containsKey("value")) {
      List<String> valueList = widget.parameters['value'].toString().split(",");
      log(valueList.toString(), name: "SELE");
      if (valueList.isNotEmpty) {
        checked.value.addAll(valueList);
        // checked.value.add(widget.checkValues?[widget.index]);
        log(widget.checkValues[widget.index].toString(), name: "CHECKED");
        var entries = checked.value.asMap().entries;
        Map<int, dynamic> data = Map.fromEntries(entries);
        Map<String, dynamic> stringedData = data.map((key, value) {
          return MapEntry(key.toString(), value);
        });

        AbstractField.fieldsData
            .addAll({widget.parameters['id']: json.encode(stringedData)});
      }
      log(checked.value.toString(), name: "CHECKED");
    }

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    log(widget.parameters['image'].toString());
    return ValueListenableBuilder(
      valueListenable: checked,
      builder: (context, List value, Widget? c) {
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Container(
                  width: 48.rw(context),
                  height: 48.rh(context),
                  decoration: BoxDecoration(
                    color: context.color.tertiaryColor.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Container(
                    height: 24,
                    width: 24,
                    child: FittedBox(
                      fit: BoxFit.none,
                      child: UiUtils.imageType(widget.parameters['image'],
                          color: Constant.adaptThemeColorSvg
                              ? context.color.tertiaryColor
                              : null,
                          width: 24,
                          height: 24,
                          fit: BoxFit.cover),
                    ),
                  ),
                ),
                SizedBox(
                  width: 10.rw(context),
                ),
                Text(widget.parameters['name'])
                    .size(context.font.large)
                    .bold(weight: FontWeight.w500)
                    .color(context.color.textColorDark)
              ],
            ),
            SizedBox(
              height: 14.rh(context),
            ),
            Wrap(
              alignment: WrapAlignment.start,
              runAlignment: WrapAlignment.start,
              crossAxisAlignment: WrapCrossAlignment.start,
              children: List.generate(
                widget.checkValues?.length ?? 0,
                (index) {
                  //this variable will prevent adding when state change
                  ///this will work like init state text
                  if (widget.initComplete == false &&
                      (!kDoNotReBuildThese.contains(widget.parameters['id']))) {
                    kDoNotReBuildThese.add(widget.parameters['id']);

                    // widget.initComplete = true;
                  }

                  return Padding(
                    padding: EdgeInsetsDirectional.only(
                        start: index == 0 ? 0 : 4, bottom: 4, top: 4, end: 4),
                    child: InkWell(
                      borderRadius: BorderRadius.circular(10),
                      onTap: () {
                        if (checked.value
                            .contains(widget.checkValues?[index])) {
                          checked.value.remove(widget.checkValues?[index]);
                          // ignore: invalid_use_of_protected_member
                          checked.notifyListeners();
                        } else {
                          checked.value.add(widget.checkValues?[index]);
                          // ignore: invalid_use_of_protected_member
                          checked.notifyListeners();
                        }

                        var entries = checked.value.asMap().entries;
                        Map<int, dynamic> data = Map.fromEntries(entries);
                        Map<String, dynamic> temp = {};
                        data.forEach((key, value) {
                          temp[key.toString()] = value;
                        });

                        AbstractField.fieldsData.addAll(
                            {widget.parameters['id']: json.encode(temp)});
                      },
                      child: Container(
                        decoration: BoxDecoration(
                            border: Border.all(
                                color: context.color.borderColor, width: 1.5),
                            color: value.contains(widget.checkValues?[index])
                                ? context.color.tertiaryColor.withOpacity(0.1)
                                : context.color.secondaryColor,
                            borderRadius: BorderRadius.circular(10)),
                        child: Padding(
                          padding: const EdgeInsets.symmetric(
                              vertical: 8.0, horizontal: 14),
                          child: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              Icon(
                                value.contains(widget.checkValues?[index])
                                    ? Icons.done
                                    : Icons.add,
                                color:
                                    value.contains(widget.checkValues?[index])
                                        ? context.color.tertiaryColor
                                        : context.color.textColorDark,
                              ),
                              const SizedBox(
                                width: 5,
                              ),
                              Text(widget.checkValues?[index]).color(
                                  value.contains(widget.checkValues?[index])
                                      ? context.color.tertiaryColor
                                      : context.color.textLightColor)
                            ],
                          ),
                        ),
                      ),
                    ),
                  );

                  return Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Checkbox(
                        fillColor: MaterialStatePropertyAll(
                            context.color.tertiaryColor),
                        value: value.contains(widget.checkValues?[index]),
                        onChanged: (v) {
                          if (checked.value
                              .contains(widget.checkValues?[index])) {
                            checked.value.remove(widget.checkValues?[index]);
                            // ignore: invalid_use_of_protected_member
                            checked.notifyListeners();
                          } else {
                            checked.value.add(widget.checkValues?[index]);
                            // ignore: invalid_use_of_protected_member
                            checked.notifyListeners();
                          }

                          var entries = checked.value.asMap().entries;
                          Map<int, dynamic> data = Map.fromEntries(entries);
                          Map<String, dynamic> temp = {};
                          data.forEach((key, value) {
                            temp[key.toString()] = value;
                          });

                          AbstractField.fieldsData.addAll(
                              {widget.parameters['id']: json.encode(temp)});
                        },
                      ),
                      Text(widget.checkValues?[index])
                    ],
                  );
                },
              ),
            )
          ],
        );
      },
    );
  }
}

class CustomTextFieldDynamic extends StatefulWidget {
  final String? value;
  final bool initController;
  final dynamic id;
  final String hintText;
  final TextInputType? keyboardType;
  final TextInputAction? action;
  final List<TextInputFormatter>? formaters;
  const CustomTextFieldDynamic({
    Key? key,
    required this.initController,
    required this.value,
    this.id,
    required this.hintText,
    this.keyboardType,
    this.action,
    this.formaters,
  }) : super(key: key);

  @override
  State<CustomTextFieldDynamic> createState() => CustomTextFieldDynamicState();
}

class CustomTextFieldDynamicState extends State<CustomTextFieldDynamic> {
  TextEditingController? _controller;

  @override
  void initState() {
    if (widget.initController) {
      _controller = TextEditingController(text: widget.value);
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return CustomTextFormField(
      hintText: widget.hintText,
      action: widget.action,
      formaters: widget.formaters,
      validator: CustomTextFieldValidator.nullCheck,
      keyboard: widget.keyboardType,
      controller: _controller,
      onChange: (value) {
        AbstractField.fieldsData.addAll({widget.id: value});
      },
    );
  }
}

class CustomDropdownState extends StatefulWidget {
  final ValueNotifier dropDownItemChange;
  final Map parameters;
  final List items;
  CustomDropdownState(
      {Key? key,
      required this.dropDownItemChange,
      required this.parameters,
      required this.items})
      : super(key: key);

  @override
  State<CustomDropdownState> createState() => _CustomDropdownStateState();
}

class _CustomDropdownStateState extends State<CustomDropdownState>
    with AutomaticKeepAliveClientMixin {
  List<DropdownMenuItem<Object>>? wid = [];
  @override
  void initState() {
    wid = widget.items
        .map((e) => DropdownMenuItem(
              value: e,
              child: Text(
                e,
              ),
            ))
        .toList();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);

    return ValueListenableBuilder(
        valueListenable: widget.dropDownItemChange,
        builder: (context, value, child) {
          log("$value and ${widget.items}", name: "VALUEIS");

          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Container(
                    width: 48.rw(context),
                    height: 48.rh(context),
                    decoration: BoxDecoration(
                      color: context.color.tertiaryColor.withOpacity(
                        0.1,
                      ),
                      borderRadius: BorderRadius.circular(
                        10,
                      ),
                    ),
                    child: Container(
                      height: 24,
                      width: 24,
                      child: FittedBox(
                        fit: BoxFit.none,
                        child: UiUtils.imageType(widget.parameters['image'],
                            color: Constant.adaptThemeColorSvg
                                ? context.color.tertiaryColor
                                : null,
                            width: 24,
                            height: 24,
                            fit: BoxFit.cover),
                      ),
                    ),
                  ),
                  SizedBox(
                    width: 10.rw(
                      context,
                    ),
                  ),
                  Text(
                    widget.parameters['name'],
                  )
                      .size(
                        context.font.large,
                      )
                      .bold(weight: FontWeight.w500)
                      .color(
                        context.color.textColorDark,
                      )
                ],
              ),
              SizedBox(
                height: 14.rh(context),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(
                  horizontal: 0,
                ),
                child: Container(
                  decoration: BoxDecoration(
                      color: context.color.secondaryColor,
                      borderRadius: BorderRadius.circular(
                        10,
                      ),
                      border: Border.all(
                        width: 1.5,
                        color: context.color.borderColor,
                      )),
                  child: Padding(
                    padding: const EdgeInsets.all(
                      8.0,
                    ),
                    child: SizedBox(
                      width: double.infinity,
                      child: DropdownButton(
                        value: value,
                        dropdownColor: context.color.secondaryColor,
                        isExpanded: true,
                        padding: const EdgeInsets.symmetric(vertical: 5),
                        icon: SvgPicture.asset(AppIcons.downArrow),
                        isDense: true,
                        borderRadius: BorderRadius.circular(
                          10,
                        ),
                        style: TextStyle(
                            color: context.color.textLightColor,
                            fontSize: context.font.large),
                        underline: const SizedBox.shrink(),
                        items: wid,
                        onChanged: (dynamic v) {
                          widget.dropDownItemChange.value = v;
                          AbstractField.fieldsData.addAll(
                            {
                              widget.parameters['id']: v,
                            },
                          );
                        },
                      ),
                    ),
                  ),
                ),
              ),
            ],
          );
        });
  }

  @override
  bool get wantKeepAlive => true;
}
