import 'dart:math';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_ui/index.dart';
import 'package:fis_ui/interface/interactive_container.dart';
import 'package:flutter/material.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/lab/color/lab_colors.dart';
import 'package:flyinsono/lab/env/env.dart';
import 'package:flyinsono/lab/manager/interfaces/task.dart';
import 'package:flyinsono/lab/manager/task_manager.dart';
import 'package:flyinsono/pages/main/home/widgets/dialog_page.dart';
import 'package:flyinsono/pages/schedule/schedule_notification/notification_card.dart';
import 'package:flyinsono/pages/schedule/schedule_notification/schedule_notification_controller.dart';
import 'package:get/get.dart';

/// 全局消息通知层
class FGlobalNotificationLayer extends FStatefulWidget
    implements FInteractiveContainer {
  const FGlobalNotificationLayer({Key? key, required this.child})
      : super(key: key);
  final FWidget child;

  @override
  FGlobalNotificationLayerState createState() =>
      FGlobalNotificationLayerState();

  @override
  String get pageName => 'FGlobalNotificationLayer';
}

class FGlobalNotificationLayerState extends FState<FGlobalNotificationLayer> {
  late ScheduleNotificationController notificationController;
  List<ApplicationNotification> notifications = [];
  final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
  final ScrollController _scrollController = ScrollController();
  static const double _notificationWidth = 420;
  final taskManager = Get.find<IServerTaskManager>();
  bool get _isShowCloseAll => notifications.length > 2;

  @override
  void initState() {
    super.initState();
    Get.put<FWebviewInteractiveController>(FWebviewInteractiveController());
    if (!kIsLab) {
      notificationController = Get.find<ScheduleNotificationController>();
      notificationController.onReceiveNotification
          .addListener(_onReceiveNotification);
    } else {
      taskManager.onReceiveNotification.addListener(_onReceiveNotification);
    }
  }

  @override
  void dispose() {
    super.dispose();
    if (kIsLab) {
      taskManager.onReceiveNotification.removeListener(_onReceiveNotification);
    } else {
      notificationController.onReceiveNotification
          .removeListener(_onReceiveNotification);
    }
  }

  void _onReceiveNotification(e, ApplicationNotification notification) {
    _insertNotification(notifications.length, notification);
  }

  // 新增消息
  void _insertNotification(index, ApplicationNotification item) {
    Get.find<FWebviewInteractiveController>().onDialogCreate();
    if (_listKey.currentState is! AnimatedListState) return;
    if (item.type == NotificationType.countdown &&
        notifications.any((element) =>
            element.type == NotificationType.countdown &&
            element.code == item.code)) {
      return;
    }
    notifications.insert(index, item);
    _listKey.currentState!.insertItem(index);
    setState(() {});
  }

  // 移除消息
  void _removeNotification(index) {
    Get.find<FWebviewInteractiveController>().onDialogDispose();
    if (_listKey.currentState is! AnimatedListState) return;
    final ApplicationNotification notificationToRemove = notifications[index];
    notifications.removeAt(index);
    _listKey.currentState!.removeItem(
        index,
        (context, animation) => _buildNotificationSizeOut(
            context, index, animation, notificationToRemove),
        duration: const Duration(milliseconds: 120));
    setState(() {});
  }

  /// 滑动式移除
  void _removeNotificationSliderOut(index) {
    Get.find<FWebviewInteractiveController>().onDialogDispose();
    if (_listKey.currentState is! AnimatedListState) return;
    final ApplicationNotification notificationToRemove = notifications[index];
    notifications.removeAt(index);
    _listKey.currentState!.removeItem(
        index,
        (context, animation) => _buildNotificationSliderOut(
            context, index, animation, notificationToRemove),
        duration: const Duration(milliseconds: 200));
    setState(() {});
  }

  /// 瞬间移除
  void _removeNotificationInstant(index) {
    Get.find<FWebviewInteractiveController>().onDialogDispose();
    if (_listKey.currentState is! AnimatedListState) return;
    final ApplicationNotification notificationToRemove = notifications[index];
    notifications.removeAt(index);
    _listKey.currentState!.removeItem(
        index,
        (context, animation) =>
            _buildNotificationToRemove(notificationToRemove),
        duration: const Duration(milliseconds: 0));
    setState(() {});
  }

  void _closeAll() {
    final animateFrame = min(notifications.length, 8);
    final int total = notifications.length;
    for (var i = 0; i < total; i++) {
      if (total - i > animateFrame) {
        _removeNotificationInstant(0);
      } else {
        Future.delayed(Duration(milliseconds: 100 * (i + animateFrame - total)),
            () {
          _removeNotificationSliderOut(0);
        });
      }
    }
  }

  @override
  FWidget build(BuildContext context) {
    return FStack(
      children: [
        widget.child,
        FPositioned(
          bottom: kIsLab ? 36 : 0,
          right: kIsLab ? null : 0,
          left: kIsLab ? 0 : null,
          child: FSizedBox(
            width: _notificationWidth,
            child: FAlign(
              alignment: Alignment.bottomRight,
              child: QuickFWidget(
                AnimatedList(
                  key: _listKey,
                  initialItemCount: notifications.length,
                  controller: _scrollController,
                  shrinkWrap: true,
                  itemBuilder: _buildNotificationFromRightSliderIn,
                ),
              ),
            ),
          ),
        ),
        if (_isShowCloseAll) _buildCloseAllButton()
        // _buildCloseAllButton()
      ],
    );
  }

  // 从右侧划入
  Widget _buildNotificationFromRightSliderIn(
      BuildContext context, int index, Animation<double> animation) {
    return SlideTransition(
      position: Tween<Offset>(
        begin: const Offset(1, 0),
        end: Offset.zero,
      ).animate(CurvedAnimation(
          parent: animation,
          curve: Curves.fastOutSlowIn,
          reverseCurve: Curves.fastOutSlowIn.flipped)),
      child: SizeTransition(
        axis: Axis.vertical,
        sizeFactor: animation,
        child: _buildNotificationCard(index),
      ),
    );
  }

  /// 收缩移除
  Widget _buildNotificationSizeOut(BuildContext context, int index,
      Animation<double> animation, ApplicationNotification notification) {
    return SizeTransition(
      axis: Axis.vertical,
      sizeFactor: animation,
      child: _buildNotificationToRemove(notification),
    );
  }

  /// 滑动移除
  Widget _buildNotificationSliderOut(BuildContext context, int index,
      Animation<double> animation, ApplicationNotification notification) {
    return SlideTransition(
      position: Tween<Offset>(
        begin: const Offset(1, 0),
        end: Offset.zero,
      ).animate(CurvedAnimation(
          parent: animation,
          curve: Curves.fastOutSlowIn,
          reverseCurve: Curves.fastOutSlowIn.flipped)),
      child: SizeTransition(
        axis: Axis.vertical,
        sizeFactor: animation,
        child: _buildNotificationToRemove(notification),
      ),
    );
  }

  Widget _buildNotificationCard(int index) {
    return FNotificationCard(
      notification: notifications[index],
      onClose: () {
        _removeNotification(index);
      },
    );
  }

  Widget _buildNotificationToRemove(ApplicationNotification notification) {
    return FNotificationCard(
      notification: notification,
      onClose: () {},
    );
  }

  FWidget _buildCloseAllButton() {
    return FPositioned(
      right: kIsLab ? null : 20,
      top: 20,
      left: kIsLab ? 20 : null,
      child: FSizedBox(
        height: 40,
        child: FElevatedButton.icon(
          name: 'closeAll',
          businessParent: widget,
          style: ButtonStyle(
            backgroundColor: MaterialStateProperty.all(kIsLab
                ? LabColors.dialogHeaderColor
                : Color.fromARGB(255, 87, 88, 88)),
          ),
          icon: const Icon(Icons.close),
          onPressed: () {
            _closeAll();
          },
          label: Text('${i18nBook.notification.closeAll.translate([
                notifications.length.toString()
              ])}'),
        ),
      ),
    );
  }
}
