import 'package:flutter/material.dart';

import 'package:uco_mobile_poc/app/res/app_colors.dart';

class SpeedDial extends StatefulWidget {
  const SpeedDial({
    Key? key,
    required this.child,
    required this.speedDialChildren,
    this.labelsStyle,
    this.labelsBackgroundColor,
    this.controller,
    this.closedForegroundColor,
    this.openForegroundColor,
    this.closedBackgroundColor,
    this.openBackgroundColor,
  }) : super(key: key);

  final Widget child;

  /// A list of [SpeedDialChild] to display when the [SpeedDial] is open.
  final List<SpeedDialChild> speedDialChildren;

  /// Specifies the [SpeedDialChild] label text style.
  final TextStyle? labelsStyle;

  /// The background color of the labels.
  final Color? labelsBackgroundColor;

  /// An animation controller for the [SpeedDial].
  ///
  /// Provide an [AnimationController] to control the animations
  /// from outside the [SpeedDial] widget.
  final AnimationController? controller;

  /// The color of the [SpeedDial] button foreground when closed.
  ///
  /// The [SpeedDial] foreground will animate to this color when the user
  /// closes the speed dial.
  final Color? closedForegroundColor;

  /// The color of the [SpeedDial] button foreground when opened.
  ///
  /// The [SpeedDial] foreground will animate to this color when the user
  /// opens the speed dial.
  final Color? openForegroundColor;

  /// The color of the [SpeedDial] button background when closed.
  ///
  /// The [SpeedDial] background will animate to this color when the user
  /// closes the speed dial.
  final Color? closedBackgroundColor;

  /// The color of the [SpeedDial] button background when open.
  ///
  /// The [SpeedDial] background will animate to this color when the user
  /// opens the speed dial.
  final Color? openBackgroundColor;

  @override
  State<StatefulWidget> createState() {
    return _SpeedDialState();
  }
}

class _SpeedDialState extends State<SpeedDial>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<Color?> _backgroundColorAnimation;
  late Animation<Color?> _foregroundColorAnimation;
  final List<Animation<double>> _speedDialChildAnimations =
      <Animation<double>>[];

  @override
  void initState() {
    _animationController = widget.controller ??
        AnimationController(
            vsync: this, duration: const Duration(milliseconds: 100));
    _animationController.addListener(() {
      if (mounted) {
        setState(() {});
      }
    });

    _backgroundColorAnimation = ColorTween(
      begin: widget.closedBackgroundColor,
      end: widget.openBackgroundColor,
    ).animate(_animationController);

    _foregroundColorAnimation = ColorTween(
      begin: widget.closedForegroundColor,
      end: widget.openForegroundColor,
    ).animate(_animationController);

    final double fractionOfOneSpeedDialChild =
        1.0 / widget.speedDialChildren.length;
    for (int speedDialChildIndex = 0;
        speedDialChildIndex < widget.speedDialChildren.length;
        ++speedDialChildIndex) {
      final List<TweenSequenceItem<double>> tweenSequenceItems =
          <TweenSequenceItem<double>>[];

      final double firstWeight =
          fractionOfOneSpeedDialChild * speedDialChildIndex;
      if (firstWeight > 0.0) {
        tweenSequenceItems.add(TweenSequenceItem<double>(
          tween: ConstantTween<double>(0.0),
          weight: firstWeight,
        ));
      }

      tweenSequenceItems.add(TweenSequenceItem<double>(
        tween: Tween<double>(begin: 0.0, end: 1.0),
        weight: fractionOfOneSpeedDialChild,
      ));

      final double lastWeight = fractionOfOneSpeedDialChild *
          (widget.speedDialChildren.length - 1 - speedDialChildIndex);
      if (lastWeight > 0.0) {
        tweenSequenceItems.add(TweenSequenceItem<double>(
            tween: ConstantTween<double>(1.0), weight: lastWeight));
      }

      _speedDialChildAnimations.insert(
          0,
          TweenSequence<double>(tweenSequenceItems)
              .animate(_animationController));
    }

    super.initState();
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //

    int speedDialChildAnimationIndex = 0;

    return _animationController.isDismissed
        ? GestureDetector(
            onTap: () {
              if (_animationController.isDismissed) {
                _animationController.forward();
              } else {
                _animationController.reverse();
              }
            },
            child: Container(
              width: 60,
              height: 60,
              clipBehavior: Clip.none,
              padding: const EdgeInsets.all(14),
              margin: EdgeInsets.only(
                top: 18,
                right: Directionality.of(context) == TextDirection.ltr ? 16 : 0,
                left: Directionality.of(context) == TextDirection.rtl ? 16 : 0,
              ),
              decoration: BoxDecoration(
                color: Colors.white,
                shape: BoxShape.circle,
                // borderRadius: BorderRadius.circular(60),
                border: Border.all(color: AppColors.colorPrimary, width: 2),
              ),
              child: widget.child,
            ),
          )
        : GestureDetector(
            onTap: () {
              if (_animationController.isDismissed) {
                _animationController.forward();
              } else {
                _animationController.reverse();
              }
            },
            child: OverflowBox(
              maxWidth: MediaQuery.sizeOf(context).width + 32,
              child: Container(
                color: Colors.black.withOpacity(0.4),
                width: MediaQuery.sizeOf(context).width + 32,
                child: Column(
                  mainAxisSize: _animationController.isDismissed
                      ? MainAxisSize.max
                      : MainAxisSize.max,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: <Widget>[
                    if (!_animationController.isDismissed)
                      Padding(
                        padding: EdgeInsets.only(
                          right: Directionality.of(context) == TextDirection.ltr
                              ? 24
                              : 0,
                          left: Directionality.of(context) == TextDirection.rtl
                              ? 24
                              : 0,
                        ),
                        child: GestureDetector(
                          onTap: () {
                            if (_animationController.isDismissed) {
                              _animationController.forward();
                            } else {
                              _animationController.reverse();
                            }
                          },
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.end,
                            children: widget.speedDialChildren
                                .map<Widget>((SpeedDialChild speedDialChild) {
                              final Widget speedDialChildWidget = Opacity(
                                opacity: _speedDialChildAnimations[
                                        speedDialChildAnimationIndex]
                                    .value,
                                child: Row(
                                  mainAxisAlignment: MainAxisAlignment.end,
                                  crossAxisAlignment: CrossAxisAlignment.end,
                                  children: <Widget>[
                                    if (speedDialChild.label != null)
                                      Padding(
                                        padding: const EdgeInsets.only(
                                            right: 16.0 - 4.0),
                                        child: GestureDetector(
                                          onTap: () => _onTap(speedDialChild),
                                          child: Padding(
                                            padding: const EdgeInsets.symmetric(
                                                horizontal: 16.0,
                                                vertical: 8.0),
                                            child: Text(
                                              speedDialChild.label!,
                                              style: widget.labelsStyle,
                                            ),
                                          ),
                                        ),
                                      ),
                                    ScaleTransition(
                                      scale: _speedDialChildAnimations[
                                          speedDialChildAnimationIndex],
                                      child: GestureDetector(
                                        onTap: () => _onTap(speedDialChild),
                                        child: Container(
                                          width: 45,
                                          height: 45,
                                          clipBehavior: Clip.none,
                                          padding: const EdgeInsets.all(10),
                                          margin: EdgeInsets.only(
                                            top: 18,
                                            right: Directionality.of(context) ==
                                                    TextDirection.ltr
                                                ? 14
                                                : 0,
                                            left: Directionality.of(context) ==
                                                    TextDirection.rtl
                                                ? 14
                                                : 0,
                                          ),
                                          decoration: BoxDecoration(
                                            color: Colors.white,
                                            shape: BoxShape.circle,
                                            // borderRadius: BorderRadius.circular(60),
                                            border: Border.all(
                                                color: AppColors.colorPrimary,
                                                width: 2),
                                          ),
                                          child: speedDialChild.child,
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              );
                              speedDialChildAnimationIndex++;
                              return speedDialChildWidget;
                            }).toList(),
                          ),
                        ),
                      ),
                    GestureDetector(
                      onTap: () {
                        if (_animationController.isDismissed) {
                          _animationController.forward();
                        } else {
                          _animationController.reverse();
                        }
                      },
                      child: Container(
                        width: 60,
                        height: 60,
                        clipBehavior: Clip.none,
                        padding: const EdgeInsets.all(14),
                        margin: EdgeInsets.only(
                          top: 18,
                          right: Directionality.of(context) == TextDirection.ltr
                              ? 32
                              : 0,
                          left: Directionality.of(context) == TextDirection.rtl
                              ? 32
                              : 0,
                        ),
                        decoration: BoxDecoration(
                          color: Colors.white,
                          shape: BoxShape.circle,
                          // borderRadius: BorderRadius.circular(60),
                          border: Border.all(
                              color: AppColors.colorPrimary, width: 2),
                        ),
                        child: widget.child,
                      ),
                    ),
                    SizedBox(height: 24),
                  ],
                ),
              ),
            ),
          );
  }

  void _onTap(SpeedDialChild speedDialChild) {
    if (speedDialChild.closeSpeedDialOnPressed) {
      _animationController.reverse();
    }
    speedDialChild.onPressed.call();
  }

// Padding(
// padding: const EdgeInsets.symmetric(vertical: 4.0),
// child: FloatingActionButton(
// heroTag: speedDialChildAnimationIndex,
// mini: true,
// foregroundColor: speedDialChild.foregroundColor,
// backgroundColor: speedDialChild.backgroundColor,
// onPressed: () => _onTap(speedDialChild),
// child: speedDialChild.child,
// ),
// )
}

class SpeedDialChild {
  const SpeedDialChild({
    required this.child,
    required this.onPressed,
    this.foregroundColor,
    this.backgroundColor,
    this.label,
    this.closeSpeedDialOnPressed = true,
  });

  /// A widget to display as the [SpeedDialChild].
  final Widget child;

  /// A callback to be executed when the [SpeedDialChild] is pressed.
  final Function onPressed;

  /// The [SpeedDialChild] foreground color.
  final Color? foregroundColor;

  /// The [SpeedDialChild] background color.
  final Color? backgroundColor;

  /// The text displayed next to the [SpeedDialChild] when the [SpeedDial] is open.
  final String? label;

  /// Whether the [SpeedDial] should close after the [onPressed] callback of
  /// [SpeedDialChild] is called.
  ///
  /// Defaults to [true].
  final bool closeSpeedDialOnPressed;
}
