/*
 *
 * 路由封装 
 * @params* [context]  当前页面上下文
 * @params* [targetPage] 跳转页面   非命名参数跳转时是 BuildContext 类型，路由命名参数跳转时是 字符串类型
 * @params [isPushNamed] 是否是命名参数跳转 默认false 非命名参数跳转; true 是 
 * @params [arguments] 携带的参数 默认null
 * @params  [opaque] 是否背景透明  默认false 不透明;  true为透明
 * @params [isReplace] 是否替换当前页面 A-B 默认0 不替换； // 0 不替换  1 替换当前 2 替换当前及之前所有
 * @params [cb] // 返回上一级的回调函数 value 为传给上一级的参数
 * 
 * 
 * 
 * 用法： 
* // 页面跳转
    GotoPage.pushPage(
      context: context,
      // targetPage: AppRoutes.mePage,
      targetPage: MePage(),
      animationType: AnimationType.rightToLeft,
      arguments: {"name": "gaolong"},
      cb: (value) => {print("---mePage返回的数据---$value------")},
    );
 * 
 * 
 * 
 */

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'device_utils.dart';


//页面跳转动画的方式
enum AnimationType { rightToLeft, leftToRight, bottomToTop, topToBottom }

class GotoPage {
  // 非命名方式跳转 直接初始化页面对象
  static void _switchPageNotNamed({
    required BuildContext context,
    required dynamic targetPage,
    AnimationType? animationType = AnimationType.rightToLeft,
    int startMills = 300, // 动画过渡时间 300ms
    Object? arguments,
    num isReplace = 0, // 0 不替换  1 替换当前 2 替换当前及之前所有
    void Function(dynamic value)? cb,
  }) {
    PageRoute pageRoute;
    if (DeviceUtils.isAndroid) {
      // 安卓
      pageRoute = PageRouteBuilder(
        settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments),
        transitionDuration: Duration(milliseconds: startMills),
        transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
          return SlideTransition(
            position: _createSlideTween(animationType).animate(animation),
            child: child,
          );
        },
        pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
          return targetPage;
        },
      );
    } else if (DeviceUtils.isIOS) {
      // 苹果
      pageRoute = CupertinoPageRoute(
        builder: (BuildContext context) {
          return targetPage;
        },
        settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments),
      );
    } else {
      // 其他
      pageRoute = MaterialPageRoute(
        builder: (BuildContext context) {
          return targetPage;
        },
        settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments),
      );
    }

    if (isReplace == 0) {
      // 不替换
      Navigator.of(context).push(pageRoute).then((value) {
        if (cb != null) {
          cb(value);
        }
      });
    } else if (isReplace == 1) {
      // 替换当前
      Navigator.of(context).pushReplacement(pageRoute).then((value) {
        if (cb != null) {
          cb(value);
        }
      });
    } else {
      // 替换当前及之前所有
      Navigator.of(context).pushAndRemoveUntil(pageRoute, (Route<dynamic>? route) => route == null).then((value) {
        if (cb != null) {
          cb(value);
        }
      });
    }
  }

  // 命名路由方式跳转
  static void _switchPageByNamed({
    required BuildContext context,
    required String targetPage,
    AnimationType? animationType = AnimationType.rightToLeft,
    int startMills = 300, // 动画过渡时间 300ms
    Object? arguments,
    num isReplace = 0, // 0 不替换  1 替换当前 2 替换当前及之前所有
    void Function(dynamic value)? cb, // 返回上一级的回调函数 value 为传给上一级的参数
  }) {
    if (isReplace == 0) {
      // 不替换
      Navigator.of(context).pushNamed(targetPage, arguments: arguments).then((value) => {
            if (cb != null) {cb(value)}
          });
    } else if (isReplace == 1) {
      // 替换当前
        Navigator.of(context).pushReplacementNamed(targetPage, arguments: arguments).then((value) => {
            if (cb != null) {cb(value)}
          });
    } else {
      // 替换当前及以前所有
      Navigator.of(context)
          .pushNamedAndRemoveUntil(targetPage, (Route route) => false, arguments: arguments)
          .then((value) => {
                if (cb != null) {cb(value)}
              });
    }
  }

  /// 1、普通跳转
  static void pushPage({
    required BuildContext context,
    required dynamic targetPage, // 非命名跳转时类型是 PageRoute  命令跳转时是 String
    AnimationType? animationType = AnimationType.rightToLeft,
    int startMills = 300, // 动画过渡时间 300ms
    Object? arguments, //携带参数
    num isReplace = 0, // 0 不替换  1 替换当前  2 替换当前及之前所有
    void Function(dynamic value)? cb, // 返回上一级的回调函数 value 为传给上一级的参数
  }) {
    bool _isPushNamed = targetPage is String ? true : false;
    if (!_isPushNamed) {
      //非路由命名方式跳转
      _switchPageNotNamed(
        context: context,
        targetPage: targetPage,
        animationType: animationType,
        startMills: startMills,
        arguments: arguments,
        isReplace: isReplace,
        cb: cb,
      );
    } else {
      // 路由命名跳转
      _switchPageByNamed(
        context: context,
        targetPage: targetPage,
        animationType: animationType,
        startMills: startMills,
        arguments: arguments,
        isReplace: isReplace,
        cb: cb,
      );
    }
  }

  /// 2、滑动过渡跳转
  static void pushPageBySlide({
    required BuildContext context,
    required dynamic targetPage, // 非命名跳转时类型是 PageRoute  命令跳转时是 String
    //默认'rightToLeft'， 'leftToRight' 'bottomToTop' 'topToBottom'
    AnimationType? animationType = AnimationType.rightToLeft,
    bool? isPushNamed = true, // 是否是路由命名跳转  true 是 false 否
    bool opaque = true, // 背景透明方式  true: 不透明  false: 透明
    Object? arguments,
    int startMills = 300,
    num isReplace = 0, // 0 不替换  1 替换当前 2 替换当前及之前所有
    void Function(dynamic value)? cb, // 返回上一级的回调函数 value 为传给上一级的参数
  }) {
    bool _isPushNamed = targetPage is String ? true : false;
    if (_isPushNamed) {
      // 命名跳转 命名跳转时 没有动画效果 默认页面从 右向左切换
      _switchPageByNamed(
          context: context, targetPage: targetPage, arguments: arguments, isReplace: isReplace, cb: cb);
    } else {
      // 非命名跳转
      PageRoute pageRoute = PageRouteBuilder(
        settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments),

        ///背景透明方式  true: 不透明  false: 透明
        opaque: opaque,
        pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
          return targetPage;
        },
        transitionDuration: Duration(milliseconds: startMills),

        ///动画
        transitionsBuilder:
            (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
          return SlideTransition(
            position: _createSlideTween(animationType).animate(animation),
            child: child,
          );
        },
      );

      if (isReplace == 0) {
        /// 不替换
        Navigator.of(context).push(pageRoute).then((value) {
          if (cb != null) {
            cb(value);
          }
        });
      } else if (isReplace == 1) {
        /// 替换当前
        Navigator.of(context).pushReplacement(pageRoute).then((value) {
          if (cb != null) {
            cb(value);
          }
        });
      } else {
        /// 替换当前及之前所有
        Navigator.of(context).pushAndRemoveUntil(pageRoute, (Route<dynamic>? route) => route == null).then((value) {
          if (cb != null) {
            cb(value);
          }
        });
      }
    }
  }

  static _createSlideTween(animationType) {
    Offset currentOffset;
    switch (animationType) {
      case AnimationType.rightToLeft:
        currentOffset = Offset(1, 0);
        break;
      case AnimationType.leftToRight:
        currentOffset = Offset(-1, 0);
        break;
      case AnimationType.bottomToTop:
        currentOffset = Offset(0, 1);
        break;
      case AnimationType.topToBottom:
        currentOffset = Offset(0, -1);
        break;
      default:
        currentOffset = Offset(1, 0);
    }
    return Tween<Offset>(
      begin: currentOffset,
      end: Offset.zero,
    );
  }

  ///  3、带渐变动画跳转
  static void pushPageByFade({
    required BuildContext context,
    required Widget targetPage,
    bool opaque = false, // 背景透明方式  true: 不透明  false: 透明
    dynamic arguments,
    int startMills = 300,
    num isReplace = 0, // 0 不替换  1 替换当前 2 替换当前及之前所有
    Function(dynamic value)? cb, // 返回上一级的回调函数 value 为传给上一级的参数
  }) {
    PageRoute pageRoute = PageRouteBuilder(
      settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments ?? null),

      ///背景透明方式  true: 不透明  false: 透明
      opaque: opaque,
      pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
        return targetPage;
      },
      transitionDuration: Duration(milliseconds: startMills),

      ///动画
      transitionsBuilder:
          (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
        return FadeTransition(
          opacity: animation,
          child: child,
        );
      },
    );

    if (isReplace == 0) {
      /// 不替换
      Navigator.of(context).push(pageRoute).then((value) {
        if (cb != null) {
          cb(value);
        }
      });
    } else if (isReplace == 1) {
      /// 替换当前
      Navigator.of(context).pushReplacement(pageRoute).then((value) {
        if (cb != null) {
          cb(value);
        }
      });
    } else {
      /// 替换当前及之前所有
      Navigator.of(context).pushAndRemoveUntil(pageRoute, (Route<dynamic>? route) => route == null).then((value) {
        if (cb != null) {
          cb(value);
        }
      });
    }
  }



  static Route _createRoute(parentContext, Widget targetPage, int startMills, int reversMills, bool opaque, {dynamic arguments}) {
    return PageRouteBuilder<void>(
      settings: RouteSettings(name: parentContext?.widget?.key ?? '', arguments: arguments ?? null),
      opaque: opaque,
      // 背景透明方式  true: 不透明  false: 透明
      pageBuilder: (context, animation, secondaryAnimation) {
        return targetPage;
      },
      transitionDuration: Duration(milliseconds: startMills),
      reverseTransitionDuration: Duration(milliseconds: reversMills),
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        var rectAnimation = _createTween(parentContext).chain(CurveTween(curve: Curves.ease)).animate(animation);

        return Stack(
          children: [
            PositionedTransition(rect: rectAnimation, child: child),
          ],
        );
      },
    );
  }

  static Tween<RelativeRect> _createTween(BuildContext context) {
    var windowSize = MediaQuery.of(context).size;
    var box = context.findRenderObject() as RenderBox;
    var rect = box.localToGlobal(Offset.zero) & box.size;
    var relativeRect = RelativeRect.fromSize(rect, windowSize);

    return RelativeRectTween(
      begin: relativeRect,
      end: RelativeRect.fill,
    );
  }
}
