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

import '../player_panel_shell.dart';
import 'panel_category_meta.dart';
import 'player_panel_controller.dart';


class PlayerPanelPopover extends StatefulWidget {

  final PlayerPanelController controller;


  final Map<PlayerPanelCategory, LayerLink> anchorLinks;


  final Set<PlayerPanelCategory> downwardCategories;


  final Widget Function(PlayerPanelCategory) bodyBuilder;


  final double width;

  const PlayerPanelPopover({
    super.key,
    required this.controller,
    required this.anchorLinks,
    this.downwardCategories = const {},
    required this.bodyBuilder,
    this.width = 340,
  });

  @override
  State<PlayerPanelPopover> createState() => _PlayerPanelPopoverState();
}

class _PlayerPanelPopoverState extends State<PlayerPanelPopover>
    with SingleTickerProviderStateMixin {
  late final AnimationController _anim;
  late final Animation<double> _t;
  late final Animation<double> _scale;


  PlayerPanelCategory? _visibleCategory;


  bool _showing = false;

  @override
  void initState() {
    super.initState();
    _anim = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 180),
      reverseDuration: const Duration(milliseconds: 130),
      value: widget.controller.value != null ? 1.0 : 0.0,
    );
    _t = CurvedAnimation(
      parent: _anim,
      curve: Curves.easeOutCubic,
      reverseCurve: Curves.easeInCubic,
    );
    _scale = Tween<double>(begin: 0.96, end: 1.0).animate(_t);
    _visibleCategory = widget.controller.value;
    _showing = widget.controller.value != null;
    _anim.addStatusListener(_onStatus);
    widget.controller.addListener(_onController);
  }

  void _onController() {
    final c = widget.controller.value;
    if (c != null) {
      setState(() {
        _visibleCategory = c;
        _showing = true;
      });
      _anim.forward();
    } else {
      _anim.reverse();
    }
  }

  void _onStatus(AnimationStatus status) {
    if (status == AnimationStatus.dismissed && mounted && _showing) {
      setState(() => _showing = false);
    }
  }

  @override
  void dispose() {
    widget.controller.removeListener(_onController);
    _anim.removeStatusListener(_onStatus);
    _anim.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final category = _visibleCategory;
    if (!_showing || category == null) return const SizedBox.shrink();
    final link = widget.anchorLinks[category];
    if (link == null) return const SizedBox.shrink();
    final downward = widget.downwardCategories.contains(category);
    final maxH = (MediaQuery.of(context).size.height * 0.55).clamp(0.0, 360.0);
    return Stack(
      children: [
        Positioned.fill(
          child: GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTap: widget.controller.close,
          ),
        ),
        Positioned(
          left: 0,
          top: 0,
          child: CompositedTransformFollower(
            link: link,
            targetAnchor: downward ? Alignment.bottomRight : Alignment.topRight,
            followerAnchor: downward
                ? Alignment.topRight
                : Alignment.bottomRight,
            offset: Offset(0, downward ? 8 : -8),
            showWhenUnlinked: false,
            child: FadeTransition(
              opacity: _t,
              child: ScaleTransition(
                scale: _scale,
                alignment: downward
                    ? Alignment.topRight
                    : Alignment.bottomRight,
                child: _bubble(category, maxH),
              ),
            ),
          ),
        ),
      ],
    );
  }

  Widget _bubble(PlayerPanelCategory category, double maxHeight) {
    return CallbackShortcuts(
      bindings: <ShortcutActivator, VoidCallback>{
        const SingleActivator(LogicalKeyboardKey.escape):
            widget.controller.close,
      },
      child: Focus(
        autofocus: true,
        child: GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: () {},
          child: ConstrainedBox(
            constraints: BoxConstraints(maxHeight: maxHeight),
            child: PlayerPanelShell(
              icon: panelCategoryIcon(category),
              title: panelCategoryLabel(category),
              width: widget.width,
              onClose: widget.controller.close,
              child: widget.bodyBuilder(category),
            ),
          ),
        ),
      ),
    );
  }
}
