part of '../guru_popup.dart';

/// Created by Haoyi on 2023/5/19
///

typedef DialogTransitions = Widget Function(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget child);

enum DialogAnimation { fadeIn, scale, slideIn, rightToLeft }

extension DialogAware on GuruPopup {
  static Widget _buildScaleTransitions(
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      Widget child) {
    return Transform.scale(
        scale: animation.value,
        child: Opacity(opacity: animation.value, child: child));
  }

  static Widget _buildSlideInTransitions(
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      Widget child) {
    return SlideTransition(
      position: Tween<Offset>(
        begin: const Offset(0.0, 0.4),
        end: const Offset(0.0, 0.0),
      ).animate(animation),
      child: FadeTransition(opacity: animation, child: child),
    );
  }

  static Widget _buildRightToLeftTransitions(
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      Widget child) {
    if (animation.status == AnimationStatus.reverse) {
      return SlideTransition(
        position: Tween<Offset>(
          begin: const Offset(-1.0, 0.0),
          end: const Offset(0.0, 0.0),
        ).animate(animation),
        child: FadeTransition(opacity: animation, child: child),
      );
    } else {
      return SlideTransition(
        position: Tween<Offset>(
          begin: const Offset(1.0, 0.0),
          end: const Offset(0.0, 0.0),
        ).animate(animation),
        child: FadeTransition(opacity: animation, child: child),
      );
    }
  }

  static Widget _buildMaterialDialogTransitions(
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      Widget child) {
    return FadeTransition(
      opacity: CurvedAnimation(
        parent: animation,
        curve: Curves.easeOut,
      ),
      child: child,
    );
  }

  static DialogTransitions _buildTransitions(DialogAnimation animation) {
    switch (animation) {
      case DialogAnimation.scale:
        return _buildScaleTransitions;
      case DialogAnimation.slideIn:
        return _buildSlideInTransitions;
      case DialogAnimation.rightToLeft:
        return _buildRightToLeftTransitions;
      default:
        return _buildMaterialDialogTransitions;
    }
  }

  Future<T?> generalDialogEx<T>({
    required RoutePageBuilder pageBuilder,
    bool barrierDismissible = false,
    String? barrierLabel,
    bool replace = false,
    Color barrierColor = const Color(0x80000000),
    Duration transitionDuration = const Duration(milliseconds: 200),
    RouteTransitionsBuilder? transitionBuilder,
    GlobalKey<NavigatorState>? navigatorKey,
    RouteSettings? routeSettings,
  }) {
    if (replace) {
      assert(!barrierDismissible || barrierLabel != null);
      final nav = navigatorKey?.currentState ??
          Navigator.of(Get.overlayContext!,
              rootNavigator:
                  true); //overlay context will always return the root navigator
      return nav.pushReplacement(
          GetDialogRoute<T>(
            pageBuilder: pageBuilder,
            barrierDismissible: barrierDismissible,
            barrierLabel: barrierLabel,
            barrierColor: barrierColor,
            transitionDuration: transitionDuration,
            transitionBuilder: transitionBuilder,
            settings: routeSettings,
          ),
          result: null);
    } else {
      return Get.generalDialog(
        pageBuilder: pageBuilder,
        barrierDismissible: barrierDismissible,
        barrierLabel: barrierLabel,
        barrierColor: barrierColor,
        transitionDuration: transitionDuration,
        transitionBuilder: transitionBuilder,
        routeSettings: routeSettings,
      );
    }
  }

  Future showDialog(
      {required Widget widget,
      bool barrierDismissible = true,
      Color? barrierColor = const Color(0xAF000000),
      bool useRootNavigator = true,
      bool useSafeArea = true,
      bool ignoreBack = false,
      bool replace = false,
      AudioEffect? showAudio,
      AudioEffect? backAudio,
      Bindings? bindings,
      Duration transitionDuration = const Duration(milliseconds: 150),
      DialogAnimation animation = DialogAnimation.slideIn,
      DialogTransitions? transition,
      RouteSettings? routeSettings}) {
    if (barrierColor == null || barrierColor.value == 0) {
      barrierColor = const Color(0x01000000);
    }
    if (showAudio != null) {
      AudioEffector.instance.play(showAudio);
    }
    return generalDialogEx(
        pageBuilder: (buildContext, animation, secondaryAnimation) {
          final pageChild = widget;
          final themeData = Theme.of(Get.context!);
          bindings?.dependencies();
          Widget dialog = Builder(builder: (context) {
            return Dialog(
              backgroundColor: Colors.transparent,
              elevation: 0,
              insetPadding: EdgeInsets.zero,
              child: pageChild,
            );
          });
          if (useSafeArea) {
            dialog = SafeArea(child: dialog);
          }
          dialog = WillPopScope(
              child: dialog,
              onWillPop: () async {
                Log.d("willPopScope!");
                if (ignoreBack) {
                  return false;
                }
                if (backAudio != null) {
                  AudioEffector.instance.play(backAudio);
                }
                return true;
              });
          return dialog;
        },
        replace: replace,
        barrierColor: barrierColor,
        barrierDismissible: barrierDismissible,
        barrierLabel:
            MaterialLocalizations.of(Get.context!).modalBarrierDismissLabel,
        routeSettings: routeSettings,
        transitionDuration: transitionDuration,
        transitionBuilder: transition ?? _buildTransitions(animation));
  }

  Future showSimpleAlertDialog(
      {String? title,
      String positiveText = "ok",
      String negativeText = "cancel",
      Widget? content,
      bool barrierDismissible = true,
      VoidCallback? onPositive,
      VoidCallback? onNegative,
      bool backAfterPressed = true}) {
    return showDialog(
        barrierDismissible: barrierDismissible,
        widget: AlertDialog(
          title: Text(
            title ?? "",
          ),
          content: content,
          actions: <Widget>[
            TextButton(
              child: Text(negativeText),
              onPressed: () {
                if (backAfterPressed) {
                  Get.back();
                }
                onNegative?.call();
              },
            ),
            TextButton(
                child: Text(positiveText),
                onPressed: () {
                  if (backAfterPressed) {
                    Get.back();
                  }
                  onPositive?.call();
                }),
          ],
        ));
  }

  Future showKeyValueDialog(List<MapEntry<String, String>> list,
      {String? title}) {
    final mediaQuery = MediaQuery.of(Get.context!);
    final size = mediaQuery.size;
    final height = min(size.height * 0.65, 720.0);
    final width = min(height * 0.6, size.width * 0.85);
    final constraint = BoxConstraints(
        minHeight: height,
        maxHeight: height,
        minWidth: width,
        maxWidth: size.width);
    final listView = ListView.builder(
        shrinkWrap: true,
        itemBuilder: (context, index) {
          final entry = list[index];
          return Padding(
            padding: const EdgeInsets.symmetric(vertical: 8),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Text(entry.key,
                    style: const TextStyle(
                        color: Colors.red,
                        fontWeight: FontWeight.w700,
                        fontSize: 14)),
                SelectableText(entry.value,
                    style: const TextStyle(
                        fontWeight: FontWeight.w100, fontSize: 9))
              ],
            ),
          );
        },
        itemCount: list.length);
    final dialog = Dialog(
      child: FlexibleContainer(
          color: Colors.white,
          constraints: constraint,
          padding: const EdgeInsets.all(24),
          radius: BorderRadius.circular(4),
          child: DartExt.isNotBlank(title)
              ? Stack(
                  fit: StackFit.expand,
                  children: [
                    Positioned.fill(top: 48, child: listView),
                    Positioned(
                        left: 0,
                        right: 0,
                        top: 0,
                        height: 48,
                        child: Align(
                          alignment: Alignment.topCenter,
                          child: AutoSizeText(
                            title!,
                            minFontSize: 10,
                            style: const TextStyle(
                                fontSize: 20,
                                fontStyle: FontStyle.italic,
                                fontWeight: FontWeight.w800,
                                color: Colors.brown),
                          ),
                        ))
                  ],
                )
              : listView),
    );
    return Get.dialog(
      dialog,
      barrierColor: Colors.black54,
    );
  }

  Future showCustomDialog(
      {DialogConstraintBuilder? constraintBuilder,
      Widget? child,
      bool clip = false}) {
    return showDialog(
        widget: GuruDialogContainer(
      constraintBuilder: constraintBuilder ??
          () {
            final dialogSpec = GuruDialogContainerDesignSpec.get();
            return BoxConstraints(
                maxWidth: dialogSpec.measuredSize.width,
                minWidth: dialogSpec.measuredSize.width,
                minHeight: dialogSpec.measuredSize.height);
          },
      clip: clip,
      child: child,
    ));
  }

  Future showStandardDialog(
      {Widget? illustration,
      Widget Function(BuildContext, GuruDialogDesignSpec)? illustrationBuilder,
      bool closable = true,
      String? title,
      String? subtitle,
      String? summary,
      String? secondaryButtonText,
      Widget? primaryButtonChild,
      String? primaryButtonAction,
      String? primaryButtonLeading,
      String? primaryButtonTrailing,
      String? primaryButtonInfo,
      String? primaryButtonSummary,
      GuruButtonStyle? primaryButtonStyle,
      Widget Function(BuildContext, Size)? overridePrimaryButtonBuilder,
      List<PositionedBuilder> positionedBuilders = const [],
      DialogButtonCallback? onPrimaryButtonPressed,
      DialogButtonCallback? onSecondaryButtonPressed,
      VoidCallback? onClosed}) {
    return showDialog(
        widget: GuruStandardDialog(
            closable: closable,
            illustration: illustration,
            illustrationBuilder: illustrationBuilder,
            title: title,
            subtitle: subtitle,
            summary: summary,
            primaryButtonChild: primaryButtonChild,
            secondaryButtonText: secondaryButtonText,
            primaryButtonAction: primaryButtonAction,
            primaryButtonLeading: primaryButtonLeading,
            primaryButtonTrailing: primaryButtonTrailing,
            primaryButtonInfo: primaryButtonInfo,
            primaryButtonSummary: primaryButtonSummary,
            primaryButtonStyle: primaryButtonStyle,
            overridePrimaryButtonBuilder: overridePrimaryButtonBuilder,
            positionedBuilders: positionedBuilders,
            onPrimaryButtonPressed: onPrimaryButtonPressed,
            onSecondaryButtonPressed: onSecondaryButtonPressed,
            onClosed: onClosed));
  }

  Future showSpotlightDialog(Widget illustration,
      {String? title,
      String? subtitle,
      String? summary,
      String? secondaryButtonText,
      Widget? primaryButtonChild,
      String? primaryButtonAction,
      String? primaryButtonLeading,
      String? primaryButtonTrailing,
      String? primaryButtonInfo,
      String? primaryButtonSummary,
      GuruButtonStyle? primaryButtonStyle,
      Widget Function(BuildContext, Size)? overridePrimaryButtonBuilder,
      List<PositionedBuilder> positionedBuilders = const [],
      DialogButtonCallback? onPrimaryButtonPressed,
      DialogButtonCallback? onSecondaryButtonPressed,
      VoidCallback? onClosed}) {
    return showDialog(
        widget: GuruSpotlightDialog(
            illustration: illustration,
            title: title,
            subtitle: subtitle,
            summary: summary,
            primaryButtonChild: primaryButtonChild,
            secondaryButtonText: secondaryButtonText,
            primaryButtonAction: primaryButtonAction,
            primaryButtonLeading: primaryButtonLeading,
            primaryButtonTrailing: primaryButtonTrailing,
            primaryButtonInfo: primaryButtonInfo,
            primaryButtonSummary: primaryButtonSummary,
            primaryButtonStyle: primaryButtonStyle,
            overridePrimaryButtonBuilder: overridePrimaryButtonBuilder,
            positionedBuilders: positionedBuilders,
            onPrimaryButtonPressed: onPrimaryButtonPressed,
            onSecondaryButtonPressed: onSecondaryButtonPressed,
            onClosed: onClosed));
  }

  Future showExtendDialog(Widget illustration,
      {String? title,
      Color titleColor = Colors.white,
      String? subtitle,
      String? summary,
      Color summaryColor = Colors.white,
      BoxDecoration? contentBackground,
      String? secondaryButtonText,
      Widget? primaryButtonChild,
      String? primaryButtonAction,
      String? primaryButtonLeading,
      String? primaryButtonTrailing,
      String? primaryButtonInfo,
      String? primaryButtonSummary,
      Widget Function(BuildContext, Size)? overridePrimaryButtonBuilder,
      List<PositionedBuilder> positionedBuilders = const [],
      DialogButtonCallback? onPrimaryButtonPressed,
      DialogButtonCallback? onSecondaryButtonPressed,
      VoidCallback? onClosed}) {
    return showDialog(
        useSafeArea: false,
        widget: GuruExtendDialog(
            illustration: illustration,
            contentBackground: contentBackground,
            title: title,
            titleColor: titleColor,
            // subtitle: subtitle,
            summary: summary,
            summaryColor: summaryColor,
            primaryButtonChild: primaryButtonChild,
            // secondaryButtonText: secondaryButtonText,
            primaryButtonAction: primaryButtonAction,
            primaryButtonLeading: primaryButtonLeading,
            primaryButtonTrailing: primaryButtonTrailing,
            primaryButtonInfo: primaryButtonInfo,
            primaryButtonSummary: primaryButtonSummary,
            overridePrimaryButtonBuilder: overridePrimaryButtonBuilder,
            positionedBuilders: positionedBuilders,
            onPrimaryButtonPressed: onPrimaryButtonPressed,
            // onSecondaryButtonPressed: onSecondaryButtonPressed
            onClosed: onClosed));
  }

  Future<AlertResult> showConfirmDialog(
      {String? title,
      required String summary,
      required String negativeButtonText,
      required String positiveButtonText,
      bool ignoreBack = false,
      GuruButtonStyle negativeButtonStyle = GuruButtonStyle.negative,
      GuruButtonStyle positiveButtonStyle = GuruButtonStyle.positive,
      String? positiveButtonLeading,
      String? positiveButtonTrailing,
      String? positiveButtonInfo,
      String? positiveButtonSummary,
      DialogButtonCallback? onNegativeButtonPressed,
      DialogButtonCallback? onPositiveButtonPressed}) async {
    final result = await showDialog(
        widget: GuruConfirmDialog(
            title: title,
            summary: summary,
            negativeButtonText: negativeButtonText,
            positiveButtonText: positiveButtonText,
            negativeButtonStyle: negativeButtonStyle,
            positiveButtonStyle: positiveButtonStyle,
            positiveButtonInfo: positiveButtonInfo,
            positiveButtonLeading: positiveButtonLeading,
            positiveButtonSummary: positiveButtonSummary,
            onNegativeButtonPressed: onNegativeButtonPressed,
            onPositiveButtonPressed: onPositiveButtonPressed),
        ignoreBack: ignoreBack);
    if (result is AlertResult) {
      return result;
    }
    return AlertResult.ignore;
  }

  Future<AlertResult> showAlertDialog(
      {String? title,
      required String summary,
      required String negativeButtonText,
      required String positiveButtonText,
      bool ignoreBack = false,
      Color? negativeColor,
      Color? positiveColor}) async {
    final result = await showDialog(
      widget: GuruAlertDialog(
          title: title,
          summary: summary,
          negativeButtonText: negativeButtonText,
          positiveButtonText: positiveButtonText,
          negativeColor: negativeColor,
          positiveColor: positiveColor),
      ignoreBack: ignoreBack,
    );
    if (result is AlertResult) {
      return result;
    }
    return AlertResult.ignore;
  }

  Future showPurchaseStatusDialog() {
    return showStandardDialog(
        illustration: Image.asset("assets/images/iap_received.png"),
        title: "Purchase Status",
        subtitle: "You have successfully purchased the product",
        summary: "You can now use the product without any restrictions",
        primaryButtonChild: const Text("OK"),
        secondaryButtonText: "Cancel",
        primaryButtonAction: "OK",
        primaryButtonLeading: "assets/images/illustration.png",
        primaryButtonTrailing: "assets/images/illustration.png",
        primaryButtonInfo: "assets/images/illustration.png",
        primaryButtonSummary: "assets/images/illustration.png");
  }

  void showBitmapDialog({required AppOwnerInfo info}) async {
    final img = await AppOwnershipUtils.generateAppBitmap(info);
    GuruPopup.instance.showStandardDialog(
        title: 'Guru Game',
        subtitle: info.appName,
        illustration: Image.memory(img),
        summary:
            'This statement affirms that the "${info.appName}" app, including its content and technology, is the sole property of GURU GAME team, created and launched in ${info.lanuchYear}.',
        primaryButtonAction: 'Got it',
        onPrimaryButtonPressed: () {
          RouteCenter.instance.back();
          return DialogResult(true, null);
        });
  }
}
