import 'package:flutter/material.dart';
import 'package:flyinsono/lab/color/lab_colors.dart';
import 'package:fis_theme/theme.dart';

/// 可选的放置位置
enum DisplayPosition {
  top,
  right,
  bottom,
  left,
  topRight,
  bottomRight,
  bottomLeft,
  topLeft,
}

/// 支持自定义的纯文本提示框组件
class LabTextTooltip extends StatefulWidget {
  const LabTextTooltip({
    super.key,
    required this.message,
    required this.child,
    this.height = 26,
    this.position = DisplayPosition.top,
    this.margin = const EdgeInsets.all(0),
    this.padding = const EdgeInsets.symmetric(horizontal: 10),
    this.offset = const Offset(0, 0),
    this.decoration = defaultDecoration,
    this.textStyle = defaultTextStyle,
    this.disable = false,
  }) : super();
  final String message;
  final Widget child;
  final double height;
  final DisplayPosition position;
  final EdgeInsetsGeometry margin;
  final EdgeInsetsGeometry padding;
  final Offset offset;
  final Decoration decoration;
  final TextStyle textStyle;
  final bool disable;

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

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

  @override
  State<LabTextTooltip> createState() => LabTextTooltipState();
}

class LabTextTooltipState extends State<LabTextTooltip> {
  OverlayEntry? _entry;

  /// 需要靠Bottom定位的情况
  static const List<DisplayPosition> NEED_BOTTOM = [
    DisplayPosition.top,
    DisplayPosition.topRight,
    DisplayPosition.topLeft,
  ];

  /// 需要靠Right定位的情况
  static const List<DisplayPosition> NEED_RIGHT = [
    DisplayPosition.left,
    DisplayPosition.topLeft,
    DisplayPosition.bottomLeft,
  ];

  /// 将容器扩宽来适应上下显示时的文本居中
  static const List<DisplayPosition> NEED_ENLARGE_WIDTH = [
    DisplayPosition.top,
    DisplayPosition.bottom,
  ];

  /// 默认情况下的文本大小
  static const double DEFAULT_TEXT_SIZE = 12;

  double get _maxMessageWidth =>
      widget.message.length * widget.textStyle.fontSize!;
  double get _paddingWidth => widget.padding.horizontal;
  double get _marginWidth => widget.margin.horizontal;
  double get _enlargeWidth => _maxMessageWidth + _paddingWidth + _marginWidth;

  /// 显示 Tooltip
  void _showTooltip() {
    _createNewEntry();
  }

  /// 隐藏 Tooltip
  void _hideTooltip() {
    _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, widget.position);
    final Offset edgeOffset =
        _edgeCorrection(targetConatiner.size, target.size, overlayOffset);
    final Widget overlay = _buildOverlay(edgeOffset, widget.position);
    _entry = OverlayEntry(builder: (BuildContext context) => overlay);
    overlayState.insert(_entry!);
  }

  /// 创建 Overlay 组件
  Widget _buildOverlay(Offset offset, DisplayPosition position) {
    return Directionality(
      textDirection: Directionality.of(context),
      child: Positioned.directional(
        top: NEED_BOTTOM.contains(position) ? null : offset.dy,
        start: NEED_RIGHT.contains(position) ? null : offset.dx,
        bottom: NEED_BOTTOM.contains(position) ? offset.dy : null,
        end: NEED_RIGHT.contains(position) ? offset.dx : null,
        textDirection: Directionality.of(context),
        child: SizedBox(
          width: NEED_ENLARGE_WIDTH.contains(position) ? _enlargeWidth : null,
          child: Center(
            child: UnconstrainedBox(
              child: Transform(
                transform: Matrix4.translationValues(
                  widget.offset.dx,
                  widget.offset.dy,
                  0,
                ),
                child: Container(
                  decoration: widget.decoration,
                  height: widget.height,
                  padding: widget.padding,
                  margin: widget.margin,
                  child: Center(
                    child: DefaultTextStyle(
                      style: TextStyle(
                        decoration: TextDecoration.none,
                        fontFamily: FTheme.ins.localeSetting.fontFamily,
                      ),
                      child: Text(widget.message, style: widget.textStyle),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  /// 计算位置布局
  Offset _countOffset(Size containerSize, Size targetSize, Offset targetOffset,
      DisplayPosition position) {
    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;
    switch (position) {
      case DisplayPosition.left:
        return Offset(cw - x + w / 2, y - widget.height / 2);
      case DisplayPosition.top:
        return Offset(x - _enlargeWidth / 2, ch - y + h / 2);
      case DisplayPosition.right:
        return Offset(x + w / 2, y - widget.height / 2);
      case DisplayPosition.bottom:
        return Offset(x - _enlargeWidth / 2, y + h / 2);
      case DisplayPosition.topRight:
        return Offset(x + w / 2, ch - y + h / 2);
      case DisplayPosition.bottomRight:
        return Offset(x + w / 2, y + h / 2);
      case DisplayPosition.bottomLeft:
        return Offset(cw - x + w / 2, y + h / 2);
      case DisplayPosition.topLeft:
        return Offset(cw - x + w / 2, ch - 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) {
    if (widget.disable) {
      return widget.child;
    }
    return MouseRegion(
      onEnter: (event) {
        _showTooltip();
      },
      onExit: (event) {
        _hideTooltip();
      },
      child: Container(
        child: widget.child,
      ),
    );
  }

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

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