import 'package:flutter/material.dart';
import 'package:flyinsono/lab/color/lab_colors.dart';
import 'package:flyinsono/lab/components/operate_button/more_operate_button.dart';
import 'package:flyinsono/lab/style/lab_box_decoration.dart';

/// 更多功能扩展菜单
class MoreOperateMenu extends StatefulWidget {
  const MoreOperateMenu({
    super.key,
    required this.buttons,
  }) : super();

  final List<MoreOperateButton> buttons;

  static const defaultTextStyle = TextStyle(
    color: LabColors.text200,
    fontSize: 12,
  );

  static const defaultDecoration = BoxDecoration(
    color: LabColors.base800,
    borderRadius: BorderRadius.all(Radius.circular(4)),
  );

  @override
  State<MoreOperateMenu> createState() => MoreOperateMenuState();

  static MoreOperateMenuState? maybeOf(BuildContext context) {
    // assert(context);
    return context.findAncestorStateOfType<MoreOperateMenuState>();
  }
}

class MoreOperateMenuState extends State<MoreOperateMenu> {
  OverlayEntry? _entry;

  bool _isHoverMore = false;

  /// 显示 Overlay
  void _showOverlay() {
    if (_entry != null) {
      return;
    }
    _createNewEntry();
  }

  /// 隐藏 Overlay
  void _hideOverlay() {
    _entry?.remove();
    _entry = null;
  }

  /// 创建新的 OverlayEntry
  void _createNewEntry() {
    final OverlayState overlayState = Overlay.of(
      context,
      debugRequiredFor: widget,
    );

    final RenderBox target = context.findRenderObject()! as RenderBox;
    final RenderBox targetConatiner =
        overlayState.context.findRenderObject() as RenderBox;
    final Offset targetOffset = target.localToGlobal(
      target.size.center(Offset.zero),
      ancestor: overlayState.context.findRenderObject(),
    );
    final Offset overlayOffset =
        _countOffset(targetConatiner.size, target.size, targetOffset);
    final Offset edgeOffset =
        _edgeCorrection(targetConatiner.size, target.size, overlayOffset);
    final Widget overlay = _buildOverlay(edgeOffset);
    _entry = OverlayEntry(builder: (BuildContext context) => overlay);
    _listenButtonClicked();
    overlayState.insert(_entry!);
  }

  /// 监听按钮事件来关闭 Overlay
  void _listenButtonClicked() {
    for (final button in widget.buttons) {
      button.clicked.removeListener(_closeMoreMenu);
    }
    for (final button in widget.buttons) {
      button.clicked.addListener(_closeMoreMenu);
    }
  }

  /// 创建 Overlay 组件
  Widget _buildOverlay(
    Offset offset,
  ) {
    return Directionality(
      textDirection: Directionality.of(context),
      child: Positioned.directional(
        top: offset.dy,
        start: offset.dx,
        textDirection: Directionality.of(context),
        child: MouseRegion(
          onEnter: _handleMouseEnterMenu,
          onExit: _handleMouseExitMenu,
          child: Container(
            padding: EdgeInsets.only(top: 5),
            child: Container(
              decoration: LabBoxDecoration.base.copyWith(
                color: LabColors.base300,
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(0.1),
                    blurRadius: 2,
                    spreadRadius: 1,
                  ),
                ],
              ),
              padding: EdgeInsets.all(5),
              child: SizedBox(
                width: 100,
                child: Column(
                  children: widget.buttons,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  /// 计算位置布局
  Offset _countOffset(
      Size containerSize, Size targetSize, Offset targetOffset) {
    final double x = targetOffset.dx;
    final double y = targetOffset.dy;
    final double w = targetSize.width;
    final double h = targetSize.height;
    return Offset(x - w / 2, y + h / 2);
  }

  /// 边缘矫正
  Offset _edgeCorrection(
      Size containerSize, Size targetSize, Offset targetOffset) {
    final double x = targetOffset.dx;
    final double y = targetOffset.dy;
    final double w = targetSize.width;
    final double h = targetSize.height;
    final double cw = containerSize.width;
    final double ch = containerSize.height;
    if (x < 0) {
      return Offset(0, y);
    }
    if (x + w > cw) {
      return Offset(cw - w, y);
    }
    if (y < 0) {
      return Offset(x, 0);
    }
    if (y + h > ch) {
      return Offset(x, ch - h);
    }
    return targetOffset;
  }

  @override
  Widget build(BuildContext context) {
    Color _colorMore = _isHoverMore ? LabColors.base400 : Colors.transparent;

    return MouseRegion(
      cursor: SystemMouseCursors.click,
      onEnter: _handleMouseEnterMoreButton,
      onExit: _handleMouseExitMoreButton,
      child: Container(
        decoration: BoxDecoration(
          color: _colorMore,
          borderRadius: BorderRadius.circular(5),
        ),
        child: Container(
          width: 80,
          child: Icon(
            Icons.keyboard_arrow_down_rounded,
            size: 20,
            color: LabColors.base700,
          ),
        ),
      ),
    );
  }

  void _handleMouseEnterMoreButton(PointerEvent details) {
    _showOverlay();
    setState(() {
      _isHoverMore = true;
    });
  }

  void _handleMouseExitMoreButton(PointerEvent details) {
    setState(() {
      _isHoverMore = false;
    });
    // 如果下一帧不在菜单内，则隐藏 Overlay
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      if (!_isHoverMore) {
        _hideOverlay();
        setState(() {
          _isHoverMore = false;
        });
      }
    });
  }

  void _handleMouseEnterMenu(PointerEvent details) {
    setState(() {
      _isHoverMore = true;
    });
  }

  void _handleMouseExitMenu(PointerEvent details) {
    _hideOverlay();
    setState(() {
      _isHoverMore = false;
    });
  }

  void _closeMoreMenu() {
    _hideOverlay();
    setState(() {
      _isHoverMore = false;
    });
  }

  /// 组件入参更新时，如果 disable 为 true，则隐藏 Overlay
  @override
  void didUpdateWidget(MoreOperateMenu oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    super.dispose();
    if (_entry != null) {
      _entry?.remove();
      _entry = null;
    }
  }
}
