content: import 'package:fl_clash/common/common.dart';
  import 'package:fl_clash/enum/enum.dart';
  import 'package:fl_clash/models/models.dart';
  import 'package:fl_clash/state.dart';
  import 'package:fl_clash/widgets/open_container.dart';
  import 'package:flutter/material.dart';
  
  import 'card.dart';
  import 'input.dart';
  import 'scaffold.dart';
  import 'sheet.dart';
  
  class Delegate {
    const Delegate();
  }
  
  class RadioDelegate<T> extends Delegate {
    final T value;
    final T groupValue;
    final void Function(T?)? onChanged;
  
    const RadioDelegate({
      required this.value,
      required this.groupValue,
      this.onChanged,
    });
  }
  
  class SwitchDelegate<T> extends Delegate {
    final bool value;
    final ValueChanged<bool>? onChanged;
  
    const SwitchDelegate({
      required this.value,
      this.onChanged,
    });
  }
  
  class CheckboxDelegate<T> extends Delegate {
    final bool value;
    final ValueChanged<bool?>? onChanged;
  
    const CheckboxDelegate({
      this.value = false,
      this.onChanged,
    });
  }
  
  class OpenDelegate extends Delegate {
    final Widget widget;
    final String title;
    final double? maxWidth;
    final Widget? action;
    final bool blur;
  
    const OpenDelegate({
      required this.title,
      required this.widget,
      this.maxWidth,
      this.action,
      this.blur = true,
    });
  }
  
  class NextDelegate extends Delegate {
    final Widget widget;
    final String title;
    final double? maxWidth;
    final Widget? action;
    final bool blur;
  
    const NextDelegate({
      required this.title,
      required this.widget,
      this.maxWidth,
      this.action,
      this.blur = true,
    });
  }
  
  class OptionsDelegate<T> extends Delegate {
    final List<T> options;
    final String title;
    final T value;
    final String Function(T value) textBuilder;
    final Function(T? value) onChanged;
  
    const OptionsDelegate({
      required this.title,
      required this.options,
      required this.textBuilder,
      required this.value,
      required this.onChanged,
    });
  }
  
  class InputDelegate extends Delegate {
    final String title;
    final String value;
    final String? suffixText;
    final Function(String? value) onChanged;
    final String? resetValue;
  
    const InputDelegate({
      required this.title,
      required this.value,
      this.suffixText,
      required this.onChanged,
      this.resetValue,
    });
  }
  
  class ListItem<T> extends StatelessWidget {
    final Widget? leading;
    final Widget title;
    final Widget? subtitle;
    final EdgeInsets padding;
    final ListTileTitleAlignment tileTitleAlignment;
    final bool? dense;
    final Widget? trailing;
    final Delegate delegate;
    final double? horizontalTitleGap;
    final TextStyle? titleTextStyle;
    final TextStyle? subtitleTextStyle;
    final void Function()? onTap;
  
    const ListItem({
      super.key,
      required this.title,
      this.subtitle,
      this.leading,
      this.padding = const EdgeInsets.symmetric(horizontal: 16),
      this.trailing,
      this.horizontalTitleGap,
      this.dense,
      this.onTap,
      this.titleTextStyle,
      this.subtitleTextStyle,
      this.tileTitleAlignment = ListTileTitleAlignment.center,
    }) : delegate = const Delegate();
  
    const ListItem.open({
      super.key,
      required this.title,
      this.subtitle,
      this.leading,
      this.padding = const EdgeInsets.symmetric(horizontal: 16),
      this.trailing,
      required OpenDelegate this.delegate,
      this.horizontalTitleGap,
      this.dense,
      this.titleTextStyle,
      this.subtitleTextStyle,
      this.tileTitleAlignment = ListTileTitleAlignment.center,
    }) : onTap = null;
  
    const ListItem.next({
      super.key,
      required this.title,
      this.subtitle,
      this.leading,
      this.padding = const EdgeInsets.symmetric(horizontal: 16),
      this.trailing,
      required NextDelegate this.delegate,
      this.horizontalTitleGap,
      this.dense,
      this.titleTextStyle,
      this.subtitleTextStyle,
      this.tileTitleAlignment = ListTileTitleAlignment.center,
    }) : onTap = null;
  
    const ListItem.options({
      super.key,
      required this.title,
      this.subtitle,
      this.leading,
      this.padding = const EdgeInsets.symmetric(horizontal: 16),
      this.trailing,
      required OptionsDelegate<T> this.delegate,
      this.horizontalTitleGap,
      this.dense,
      this.titleTextStyle,
      this.subtitleTextStyle,
      this.tileTitleAlignment = ListTileTitleAlignment.center,
    }) : onTap = null;
  
    const ListItem.input({
      super.key,
      required this.title,
      this.subtitle,
      this.leading,
      this.padding = const EdgeInsets.symmetric(horizontal: 16),
      this.trailing,
      required InputDelegate this.delegate,
      this.horizontalTitleGap,
      this.dense,
      this.titleTextStyle,
      this.subtitleTextStyle,
      this.tileTitleAlignment = ListTileTitleAlignment.center,
    }) : onTap = null;
  
    const ListItem.checkbox({
      super.key,
      required this.title,
      this.subtitle,
      this.leading,
      this.padding = const EdgeInsets.only(left: 16, right: 8),
      required CheckboxDelegate<T> this.delegate,
      this.horizontalTitleGap,
      this.dense,
      this.titleTextStyle,
      this.subtitleTextStyle,
      this.tileTitleAlignment = ListTileTitleAlignment.center,
    })  : trailing = null,
          onTap = null;
  
    const ListItem.switchItem({
      super.key,
      required this.title,
      this.subtitle,
      this.leading,
      this.padding = const EdgeInsets.only(left: 16, right: 8),
      required SwitchDelegate<T> this.delegate,
      this.horizontalTitleGap,
      this.dense,
      this.titleTextStyle,
      this.subtitleTextStyle,
      this.tileTitleAlignment = ListTileTitleAlignment.center,
    })  : trailing = null,
          onTap = null;
  
    const ListItem.radio({
      super.key,
      required this.title,
      this.subtitle,
      this.trailing,
      this.padding = const EdgeInsets.only(left: 12, right: 16),
      required RadioDelegate<T> this.delegate,
      this.horizontalTitleGap = 8,
      this.dense,
      this.titleTextStyle,
      this.subtitleTextStyle,
      this.tileTitleAlignment = ListTileTitleAlignment.center,
    })  : leading = null,
          onTap = null;
  
    _buildListTile({
      void Function()? onTap,
      Widget? trailing,
      Widget? leading,
    }) {
      return ListTile(
        key: key,
        dense: dense,
        titleTextStyle: titleTextStyle,
        subtitleTextStyle: subtitleTextStyle,
        leading: leading ?? this.leading,
        horizontalTitleGap: horizontalTitleGap,
        title: title,
        minVerticalPadding: 12,
        subtitle: subtitle,
        titleAlignment: tileTitleAlignment,
        onTap: onTap,
        trailing: trailing ?? this.trailing,
        contentPadding: padding,
      );
    }
  
    @override
    Widget build(BuildContext context) {
      if (delegate is OpenDelegate) {
        final openDelegate = delegate as OpenDelegate;
        final child = SafeArea(
          child: openDelegate.widget,
        );
        return OpenContainer(
          closedBuilder: (_, action) {
            openAction() {
              final isMobile = globalState.appState.viewMode == ViewMode.mobile;
              if (!isMobile) {
                showExtend(
                  context,
                  props: ExtendProps(
                    blur: openDelegate.blur,
                    maxWidth: openDelegate.maxWidth,
                  ),
                  builder: (_, type) {
                    return AdaptiveSheetScaffold(
                      actions: [
                        if (openDelegate.action != null) openDelegate.action!,
                      ],
                      type: type,
                      body: child,
                      title: openDelegate.title,
                    );
                  },
                );
                return;
              }
              action();
            }
  
            return _buildListTile(
              onTap: openAction,
            );
          },
          openBuilder: (_, action) {
            return CommonScaffold.open(
              key: Key(openDelegate.title),
              onBack: action,
              title: openDelegate.title,
              body: child,
              actions: [
                if (openDelegate.action != null) openDelegate.action!,
              ],
            );
          },
        );
      }
      if (delegate is NextDelegate) {
        final nextDelegate = delegate as NextDelegate;
        final child = SafeArea(
          child: nextDelegate.widget,
        );
  
        return _buildListTile(
          onTap: () {
            showExtend(
              context,
              props: ExtendProps(
                blur: nextDelegate.blur,
                maxWidth: nextDelegate.maxWidth,
              ),
              builder: (_, type) {
                return AdaptiveSheetScaffold(
                  actions: [
                    if (nextDelegate.action != null) nextDelegate.action!,
                  ],
                  type: type,
                  body: child,
                  title: nextDelegate.title,
                );
              },
            );
          },
        );
      }
      if (delegate is OptionsDelegate) {
        final optionsDelegate = delegate as OptionsDelegate<T>;
        return _buildListTile(
          onTap: () async {
            final value = await globalState.showCommonDialog<T>(
              child: OptionsDialog<T>(
                title: optionsDelegate.title,
                options: optionsDelegate.options,
                textBuilder: optionsDelegate.textBuilder,
                value: optionsDelegate.value,
              ),
            );
            optionsDelegate.onChanged(value);
          },
        );
      }
      if (delegate is InputDelegate) {
        final inputDelegate = delegate as InputDelegate;
        return _buildListTile(
          onTap: () async {
            final value = await globalState.showCommonDialog<String>(
              child: InputDialog(
                title: inputDelegate.title,
                value: inputDelegate.value,
                suffixText: inputDelegate.suffixText,
                resetValue: inputDelegate.resetValue,
              ),
            );
            inputDelegate.onChanged(value);
          },
        );
      }
      if (delegate is CheckboxDelegate) {
        final checkboxDelegate = delegate as CheckboxDelegate;
        return _buildListTile(
          onTap: () {
            if (checkboxDelegate.onChanged != null) {
              checkboxDelegate.onChanged!(!checkboxDelegate.value);
            }
          },
          trailing: CommonCheckBox(
            value: checkboxDelegate.value,
            onChanged: checkboxDelegate.onChanged,
          ),
        );
      }
      if (delegate is SwitchDelegate) {
        final switchDelegate = delegate as SwitchDelegate;
        return _buildListTile(
          onTap: () {
            if (switchDelegate.onChanged != null) {
              switchDelegate.onChanged!(!switchDelegate.value);
            }
          },
          trailing: Switch(
            value: switchDelegate.value,
            onChanged: switchDelegate.onChanged,
          ),
        );
      }
      if (delegate is RadioDelegate) {
        final radioDelegate = delegate as RadioDelegate<T>;
        return _buildListTile(
          onTap: () {
            if (radioDelegate.onChanged != null) {
              radioDelegate.onChanged!(radioDelegate.value);
            }
          },
          leading: Radio<T>(
            materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
            value: radioDelegate.value,
            groupValue: radioDelegate.groupValue,
            onChanged: radioDelegate.onChanged,
          ),
          trailing: trailing,
        );
      }
  
      return _buildListTile(
        onTap: onTap,
      );
    }
  }
  
  class ListHeader extends StatelessWidget {
    final String title;
    final String? subTitle;
    final List<Widget> actions;
    final EdgeInsets? padding;
    final double? space;
  
    const ListHeader({
      super.key,
      required this.title,
      this.subTitle,
      this.padding,
      List<Widget>? actions,
      this.space,
    }) : actions = actions ?? const [];
  
    @override
    Widget build(BuildContext context) {
      return Container(
        alignment: Alignment.centerLeft,
        padding: padding ??
            const EdgeInsets.only(
              left: 16,
              right: 8,
              top: 24,
              bottom: 8,
            ),
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    title,
                    style: Theme.of(context).textTheme.labelLarge?.copyWith(
                          color: Theme.of(context)
                              .colorScheme
                              .onSurfaceVariant
                              .opacity80,
                          fontWeight: FontWeight.w600,
                        ),
                  ),
                  if (subTitle != null)
                    Text(
                      subTitle!,
                      style: Theme.of(context).textTheme.bodySmall?.copyWith(
                            color: Theme.of(context).colorScheme.outline,
                          ),
                    ),
                ],
              ),
            ),
            Row(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                ...genActions(
                  actions,
                  space: space,
                ),
              ],
            ),
          ],
        ),
      );
    }
  }
  
  List<Widget> generateSection({
    String? title,
    required Iterable<Widget> items,
    List<Widget>? actions,
    bool separated = true,
  }) {
    final genItems = separated
        ? items.separated(
            const Divider(
              height: 0,
            ),
          )
        : items;
    return [
      if (items.isNotEmpty && title != null)
        ListHeader(
          title: title,
          actions: actions,
        ),
      ...genItems,
    ];
  }
  
  Widget generateSectionV2({
    String? title,
    required Iterable<Widget> items,
    List<Widget>? actions,
    bool separated = true,
  }) {
    return Column(
      children: [
        if (items.isNotEmpty && title != null)
          ListHeader(
            title: title,
            actions: actions,
          ),
        CommonCard(
          radius: 18,
          type: CommonCardType.filled,
          child: Column(
            children: [
              ...items,
            ],
          ),
        )
      ],
    );
  }
  
  List<Widget> generateInfoSection({
    required Info info,
    required Iterable<Widget> items,
    List<Widget>? actions,
    bool separated = true,
  }) {
    final genItems = separated
        ? items.separated(
            const Divider(
              height: 0,
            ),
          )
        : items;
    return [
      if (items.isNotEmpty)
        InfoHeader(
          info: info,
          actions: actions,
        ),
      ...genItems,
    ];
  }
  
  Widget generateListView(List<Widget> items) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (_, index) => items[index],
      padding: const EdgeInsets.only(
        bottom: 16,
      ),
    );
  }
  