import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:llswidget/llswidget.dart';

class LLSToast extends StatefulWidget {
  const LLSToast({
    Key? key,
    this.child,
    this.button,
    this.backgroundColor,
    this.text,
    this.width,
    this.type = LLSToastType.basic,
    this.autoDismiss = true,
    this.alignment,
    this.animationDuration = const Duration(milliseconds: 300),
    this.duration = const Duration(milliseconds: 300),
    this.textStyle = const TextStyle(color: Colors.white70),
    this.autoDismissDuration = const Duration(milliseconds: 3000),
  }) : super(key: key);

  final Widget? child;

  final Widget? button;

  final Color? backgroundColor;

  final String? text;

  final TextStyle textStyle;

  final double? width;

  final LLSToastType type;

  final bool autoDismiss;

  final Duration animationDuration;

  final Duration duration;

  final Duration autoDismissDuration;

  final Alignment? alignment;

  @override
  _LLSToastState createState() => _LLSToastState();
}

class _LLSToastState extends State<LLSToast> with TickerProviderStateMixin {
  late AnimationController animationController, fadeAnimationController;
  late Animation<double> animation, fadeAnimation;
  Timer? timer;
  bool hideToast = false;

  @override
  void initState() {
    animationController = AnimationController(duration: widget.duration, vsync: this);
    animation = CurvedAnimation(
      parent: animationController,
      curve: Curves.easeIn,
    );

    if (mounted) {
      animationController.forward();
      fadeAnimationController =
          AnimationController(duration: widget.animationDuration, vsync: this)
            ..addListener(() => setState(() {}));
      fadeAnimation = Tween<double>(
        begin: 0,
        end: 1,
      ).animate(fadeAnimationController);
      timer = Timer(widget.duration, () {
        if (mounted) {
          fadeAnimationController.forward();
        }
      });
      fadeAnimation = Tween<double>(
        begin: 1,
        end: 0,
      ).animate(fadeAnimationController);
      fadeAnimation.addStatusListener((AnimationStatus state) {
        if (fadeAnimation.isCompleted && widget.autoDismiss) {
          setState(() {
            hideToast = true;
          });
        }
      });
    }

    super.initState();
  }

  @override
  void dispose() {
    animationController.dispose();
    fadeAnimationController.dispose();
    timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => hideToast
      ? Container()
      : FadeTransition(
          opacity: widget.autoDismiss ? fadeAnimation : animation,
          child: Column(
            children: <Widget>[
              Container(
                width: widget.type == LLSToastType.fullWidth
                    ? MediaQuery.of(context).size.width
                    : widget.width ?? MediaQuery.of(context).size.width * 0.885,
                constraints: const BoxConstraints(minHeight: 50),
                margin: widget.type == LLSToastType.fullWidth
                    ? const EdgeInsets.only(left: 0, right: 0)
                    : const EdgeInsets.only(left: 10, right: 10),
                padding: const EdgeInsets.all(10),
                decoration: BoxDecoration(
                  borderRadius: widget.type == LLSToastType.basic
                      ? BorderRadius.circular(0)
                      : widget.type == LLSToastType.rounded
                          ? BorderRadius.circular(10)
                          : BorderRadius.zero,
                  color: widget.backgroundColor ?? const Color(0xff323232),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withOpacity(0.40),
                      blurRadius: 6,
                    )
                  ]
                ),
                child: Row(
                  children: <Widget>[
                    Flexible(
                      flex: 7,
                      fit: FlexFit.tight,
                      child: Align(
                        alignment: widget.alignment ?? Alignment.topLeft,
                        child: widget.text != null
                            ? Text(widget.text!, style: widget.textStyle)
                            : (widget.child ?? Container()),
                      ),
                    ),
                    const SizedBox(
                      width: 10,
                    ),
                    widget.button != null
                        ? Flexible(
                            flex: 4,
                            fit: FlexFit.tight,
                            child: Align(
                              alignment: Alignment.topRight,
                              child: widget.button,
                            )
                        )
                        : Container()
                  ],
                ),
              ),
            ],
          ),
        );
}