part of '../guru_popup.dart';

/// Created by Haoyi on 2023/6/8

extension OverlayAware on GuruPopup {
  double _positionNipHorizontalOffset({
    required double childWidth,
    required double targetX,
    double spacing = 0.0,
  }) {
    double x;
    final width = Get.width;
    if (width - spacing * 2.0 < childWidth) {
      x = (width - childWidth) / 2.0;
      // print("_positionDependentBox x:$x size.width:$width childSize.width:$childWidth");
    } else {
      final double normalizedTargetX = targetX.clamp(spacing, width - spacing);
      final double edge = spacing + childWidth / 2.0;

      if (normalizedTargetX < edge) {
        x = spacing;
      } else if (normalizedTargetX > width - edge) {
        x = width - spacing - childWidth;
      } else {
        x = normalizedTargetX - childWidth / 2.0;
      }
      // print(
      //     "_positionDependentBox x:$x normalizedTargetX:$normalizedTargetX target:$targetX margin:$spacing edge:$edge size.width:${width} childSize.width:${childWidth}");
    }
    return targetX - x;
  }

  Completer showTipsOverlay(Rect anchorBoundary,
      {double? width,
        double? height,
        double spacing = 4,
        Color? backgroundColor,
        Gradient? gradient,
        Radius? radius,
        VoidCallback? onDismiss,
        double nipHeight = 6,
        double nipRadius = 4,
        double nipWidth = 16,
        Color barrierColor = Colors.transparent,
        Color bottomBarrierColor = Colors.transparent,
        double? leftMargin = 16,
        Widget? child}) {
    final anchorCenter = anchorBoundary.center;
    final nipOffset = _positionNipHorizontalOffset(
        childWidth: width!, targetX: anchorCenter.dx, spacing: spacing);
    // Log.d("nipOffset: $nipOffset");
    final completer = Completer();
    OverlayEntry? overlayEntry = OverlayEntry(
      builder: (BuildContext context) =>
          GestureDetector(
            onTap: () {
              onDismiss?.call();
              completer.complete();
            },
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: barrierColor,
              ),
              child: Stack(
                children: [
                  Positioned(
                    top: anchorBoundary.bottom + spacing - (Get.statusBarHeight / Get.pixelRatio),
                    left: anchorCenter.dx - nipOffset,
                    child: AnimatedTransformBuilder.single(
                      fromXScale: 0.999,
                      toXScale: 1.0,
                      fromYScale: 0.0,
                      toYScale: 1.0,
                      alignment: Alignment.topCenter,
                      curve: const Cubic(0.175, 0.885, 0.32, 1.1),
                      duration: const Duration(milliseconds: 300),
                      child: TipsWidget(
                          width: width,
                          height: height,
                          nipOffset: nipOffset,
                          nip: TipsNip.top,
                          nipHeight: nipHeight,
                          nipRadius: nipRadius,
                          nipWidth: nipWidth,
                          radius: radius,
                          gradient: gradient,
                          backgroundColor: backgroundColor,
                          child: child),
                    ),
                  ),
                ],
              ),
            ),
          ),
    );
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;
    overlayState.insert(overlayEntry);

    completer.future.then((_) {
      overlayEntry?.remove();
      overlayEntry = null;
    }).whenComplete(() {
      overlayEntry?.remove();
      overlayEntry = null;
    }).catchError((error) {
      overlayEntry?.remove();
      overlayEntry = null;
    });
    return completer;
  }

  Completer showBottomOverlay({required Widget child, bool? closable, double? height}) {
    final completer = Completer();
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;
    final designSpec = GuruDialogContainerDesignSpec.get();
    final dialogSpec = designSpec.dialogSpec;

    final td = Directionality.of(Get.overlayContext!);
    final guruTheme = GuruTheme.of(Get.overlayContext!);
    final closeIcon = guruTheme.iconScheme.closeIcon;

    final overlayEntry = OverlayEntry(
      builder: (BuildContext context) =>
          GestureDetector(
            onTap: () {
              completer.complete();
            },
            child: DecoratedBox(
              decoration: const BoxDecoration(
                color: Colors.transparent,
              ),
              child: Stack(
                children: [
                  Positioned(
                    bottom: 0,
                    left: 0,
                    child: AnimatedTransformBuilder.single(
                      fromTranslation: Offset(0, height ?? 300),
                      toTranslation: Offset.zero,
                      alignment: Alignment.topCenter,
                      curve: const Cubic(0.175, 0.885, 0.32, 1.1),
                      duration: const Duration(milliseconds: 300),
                      child: GestureDetector(
                        onTap: () {},
                        child: ClipRRect(
                          borderRadius: const BorderRadius.only(
                              topLeft: Radius.circular(20), topRight: Radius.circular(20)),
                          child: Stack(children: [
                            Container(
                                color: Colors.white,
                                height: height ?? 300,
                                width: MediaQuery
                                    .of(context)
                                    .size
                                    .width,
                                padding: dialogSpec.contentPadding,
                                child: child),
                            closable == true
                                ? Positioned.directional(
                                textDirection: td,
                                top: dialogSpec.closeButtonMargin.top,
                                start: dialogSpec.closeButtonMargin.start,
                                child: TapWidget(
                                  inkWell: true,
                                  shape: const CircleBorder(),
                                  onTap: () {
                                    completer.complete();
                                  },
                                  child: SizedBox(
                                      width: dialogSpec.closeButtonSize,
                                      height: dialogSpec.closeButtonSize,
                                      child: Center(
                                          child: (closeIcon != null)
                                              ? Image.asset(closeIcon,
                                              fit: BoxFit.contain,
                                              width: dialogSpec.closeIconSize,
                                              height: dialogSpec.closeIconSize)
                                              : Icon(Icons.close, size: dialogSpec.closeIconSize))),
                                ))
                                : Container(),
                          ]),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
    );
    completer.future.then((params) {
      overlayEntry.remove();
    }).whenComplete(() {
      Log.v("loading dialog!!! completed!");
    }).catchError((error) {
      Log.v("error dialog!!! completed!");
    });
    overlayState.insert(overlayEntry);

    return completer;
  }

  Completer showCancelableLoading(
      {Stream<bool>? cancellableStream, Stream<dynamic>? errorStream, VoidCallback? onCompleted}) {
    final completer = Completer();
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;

    final overlayEntry = OverlayEntry(
      builder: (BuildContext context) =>
          Material(
              child: Center(
                child: AnimatedTransformBuilder.single(
                    fromOpacity: 0.5,
                    toOpacity: 1,
                    fromScale: 1.1,
                    toScale: 1,
                    curve: Curves.easeInOut,
                    duration: const Duration(milliseconds: 200),
                    child: GuruCancellableLoadingWidget(
                        cancellableStream ??
                            Stream.fromFuture(
                                Future.delayed(const Duration(seconds: 5)).then((_) => true)),
                        errorStream ?? Stream.value(null),
                        completer)),
              )),
    );
    completer.future.then((params) {
      overlayEntry.remove();
    }).whenComplete(() {
      Log.v("loading overlay!!! completed!");
      onCompleted?.call();
    }).catchError((error) {
      Log.v("error overlay!!! completed!");
      onCompleted?.call();
    });
    overlayState.insert(overlayEntry);

    return completer;
  }

  Completer showSimpleLoading() {
    final completer = Completer();
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;

    final overlayEntry = OverlayEntry(
      builder: (BuildContext context) =>
      const Material(child: Center(child: GuruSimpleLoadingWidget())),
    );
    completer.future.then((params) {
      overlayEntry.remove();
    }).whenComplete(() {
      Log.v("loading dialog!!! completed!");
    }).catchError((error) {
      Log.v("error dialog!!! completed!");
    });
    overlayState.insert(overlayEntry);

    return completer;
  }

  void showStandardOverlay(String text,
      {String? icon, Duration duration = const Duration(milliseconds: 2000), String? package}) {
    final completer = Completer();
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;

    final overlayEntry = OverlayEntry(
        builder: (BuildContext context) =>
            Material(
                child: Center(
                    child: GuruStandardOverlayWidget(text: text, icon: icon, package: package)))
    );
    completer.future.then((params) {
      overlayEntry.remove();
    }).whenComplete(() {
      Log.v("loading dialog!!! completed!");
    }).catchError((error) {
      Log.v("error dialog!!! completed!");
    });
    overlayState.insert(overlayEntry);

    Future.delayed(duration, () {
      completer.complete();
    });
  }

  Completer showFeedbackLoading(
      {Stream<bool>? successStream, String? feedbackText, Widget? feedbackIcon}) {
    final completer = Completer();
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;

    final overlayEntry = OverlayEntry(
      builder: (BuildContext context) =>
          Material(
              child: Center(
                  child: GuruFeedbackLoadingWidget(
                      successStream ??
                          Stream.fromFuture(
                              Future.delayed(const Duration(seconds: 5)).then((_) => true)),
                      feedbackText: feedbackText,
                      feedbackIcon: feedbackIcon))),
    );
    completer.future.then((params) {
      overlayEntry.remove();
    }).whenComplete(() {
      Log.v("loading dialog!!! completed!");
    }).catchError((error) {
      Log.v("error dialog!!! completed!");
    });
    overlayState.insert(overlayEntry);

    return completer;
  }

  Completer showGemsOverlay() {
    final completer = Completer();
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;

    final overlayEntry = OverlayEntry(
        builder: (BuildContext context) =>
            Material(
                child: GuruGemOverlayWidget(completer: completer)));
    completer.future.then((params) {
      overlayEntry.remove();
    }).whenComplete(() {
      Log.v("loading dialog!!! completed!");
    }).catchError((error) {
      Log.v("error dialog!!! completed!");
    });
    overlayState.insert(overlayEntry);

    return completer;
  }

  Completer showAssetsOverlay(Director director) {
    final completer = Completer();
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;

    final overlayEntry = OverlayEntry(
        builder: (BuildContext context) =>
            Material(
                child: GuruAssetOverlay(director)));
    completer.future.then((params) {
      Log.v("assetsOverlay complated!!! completed!");
      overlayEntry.remove();
    }).whenComplete(() {
      Log.v("loading dialog!!! completed!");
    }).catchError((error) {
      Log.v("error dialog!!! completed!");
    });
    overlayState.insert(overlayEntry);

    return completer;
  }

  Completer showAdsBanner() {
    final completer = Completer();
    final overlayEntry = OverlayEntry(builder: (context) {
      return const Align(
        alignment: Alignment.bottomCenter,
        child: AdsBannerOverlay(),
      );
    });
    completer.future.then((params) {
      Log.v("ads banner completed!");
      overlayEntry.remove();
    }).whenComplete(() {
      Log.v("loading dialog!!! completed!");
    }).catchError((error) {
      Log.v("error dialog!!! completed!");
    });
    final navigatorState = Navigator.of(Get.overlayContext!, rootNavigator: false);
    final overlayState = navigatorState.overlay!;
    overlayState.insert(overlayEntry);
    return completer;
  }


}