import 'package:flutter/material.dart';

import 'view/cancel.dart';
import 'view/confirm.dart';
import 'view/success.dart';

import 'package:llswidget/llswidget.dart';

//Return false to keey dialog showing
typedef bool LLSAlertOnPress(bool isConfirm);

enum LLSAlertStyle { success, error, confirm, loading }

class LLSAlertOptions {
  final String? title;
  
  final String? subtitle;

  final LLSAlertOnPress? onPress;

  final Color? confirmButtonColor;

  final Color? cancelButtonColor;

  final String? confirmButtonText;

  final String? cancelButtonText;

  final bool showCancelButton;
  
  final LLSAlertStyle style;

  final TextStyle titleStyle;

  final TextStyle subtitleStyle;

  LLSAlertOptions(
    {this.showCancelButton: false,
    this.title,
    this.subtitle,
    this.onPress,
    this.cancelButtonColor,
    this.cancelButtonText,
    this.confirmButtonColor,
    this.confirmButtonText,
    this.style = LLSAlertStyle.success,
    this.titleStyle = const TextStyle(fontSize: 25.0, color: Color(0xff575757)),
    this.subtitleStyle = const TextStyle(fontSize: 16.0, color: Color(0xff797979))
  });
}

class LLSAlertDialog extends StatefulWidget {
  final Curve? curve;
  final LLSAlertOptions? options;

  LLSAlertDialog({
    this.curve,
    this.options,
  }) : assert(options != null);

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

class _LLSAlertDialogState extends State<LLSAlertDialog> with SingleTickerProviderStateMixin, LLSAlert {
  AnimationController? controller;
  Animation<double>? tween;
  LLSAlertOptions? _options;

  @override
  void initState() {
    _options = widget.options;
    controller = AnimationController(vsync: this);
    tween = Tween(begin: 0.0, end: 1.0).animate(controller!);
    controller!.animateTo(1.0,
      duration: Duration(milliseconds: 300),
      curve: widget.curve ?? LLSAlert.showCurve);

    LLSAlert._state = this;
    super.initState();
  }

  @override
  void dispose() {
    controller?.dispose();
    LLSAlert._state = null;
    super.dispose();
  }

  @override
  void didUpdateWidget(LLSAlertDialog oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  void confirm() {
    if (_options!.onPress != null && _options!.onPress!(true) == false)
      return;
    Navigator.pop(context);
  }

  void cancel() {
    if (_options!.onPress != null && _options!.onPress!(false) == false)
      return;
    Navigator.pop(context);
  }

  void update(LLSAlertOptions options) {
    setState(() {
      _options = options;
    });
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> listOfChildren = [];

    switch (_options!.style) {
      case LLSAlertStyle.success:
        listOfChildren.add(SizedBox(
          width: 64.0,
          height: 64.0,
          child: SuccessView(),
        ));
        break;
      case LLSAlertStyle.confirm:
        listOfChildren.add(SizedBox(
          width: 64.0,
          height: 64.0,
          child: ConfirmView(),
        ));
        break;
      case LLSAlertStyle.error:
        listOfChildren.add(SizedBox(
          width: 64.0,
          height: 64.0,
          child: CancelView(),
        ));
        break;
      case LLSAlertStyle.loading:
        listOfChildren.add(SizedBox(
          width: 64.0,
          height: 64.0,
          child: Center(
            child: CircularProgressIndicator(),
          ),
        ));
        break;
    }

     if (_options!.title != null) {
      listOfChildren.add(Padding(
        padding: EdgeInsets.only(top: 24.0),
        child: Center(
          child: Text(
            _options!.title!,
            style: _options!.titleStyle,
          ),
        ),
      ));
    }

    if (_options!.subtitle != null) {
      double paddingTop = 10.0;
      if (_options!.title == null) {
        paddingTop = 24.0;
      }
      listOfChildren.add(Padding(
        padding: EdgeInsets.only(top: paddingTop),
        child: Text(
          _options!.subtitle!,
          style: _options!.subtitleStyle,
        ),
      ));
    }

    if (_options!.style != LLSAlertStyle.loading) {
      if (_options!.showCancelButton) {
        listOfChildren.add(Padding(
          padding: EdgeInsets.only(top: 18.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              LLSButton(
                onPressed: cancel,
                shape: LLSButtonShape.rounded,
                child: Text(
                  _options!.cancelButtonText ?? LLSAlert.cancelText,
                ),
                color: _options!.cancelButtonColor ?? LLSColors.WARNING
              ),
              SizedBox(
                width: 10.0,
              ),
              LLSButton(
                onPressed: confirm,
                shape: LLSButtonShape.rounded,
                child: Text(
                  _options!.confirmButtonText ?? LLSAlert.confirmText,
                ),
                color: _options!.confirmButtonColor ?? LLSColors.SUCCESS
              )
            ],
          ),
        ));
      } else {
        listOfChildren.add(Padding(
          padding: EdgeInsets.only(top: 18.0),
          child: LLSButton(
            onPressed: confirm,
            shape: LLSButtonShape.rounded,
            child: Text(
              _options!.confirmButtonText ?? LLSAlert.successText
            ),
            color: _options!.confirmButtonColor ?? LLSColors.SUCCESS
          )
        ));
      }
    } else {
      listOfChildren.add(SizedBox(height: 18.0));
    }

    return Center(
      child: AnimatedBuilder(
        animation: controller!,
        builder: (c, w) {
          return ScaleTransition(
            scale: tween!,
            child: ClipRRect(
              borderRadius: BorderRadius.all(Radius.circular(5.0)),
              child: Container(
                color: Colors.white,
                width: double.infinity,
                child: Padding(
                  padding: EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 20.0),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: listOfChildren,
                  ),
                )),
            ),
          );
        }
      )
    );
  }
}

abstract class LLSAlert {
  static String successText = "OK";
  static String confirmText = "Confirm";
  static String cancelText = "Cancel";

  static Curve showCurve = Curves.bounceOut;

  static _LLSAlertDialogState? _state;

  static void show(BuildContext context,
      {Curve? curve,
      String? title,
      String? subtitle,
      bool showCancelButton: false,
      LLSAlertOnPress? onPress,
      Color? cancelButtonColor,
      Color? confirmButtonColor,
      String? cancelButtonText,
      String? confirmButtonText,
      LLSAlertStyle style: LLSAlertStyle.success,
      TextStyle? titleStyle,
      TextStyle? subtitleStyle}) {
    LLSAlertOptions options = LLSAlertOptions(
        showCancelButton: showCancelButton,
        title: title,
        subtitle: subtitle,
        style: style,
        onPress: onPress,
        confirmButtonColor: confirmButtonColor,
        confirmButtonText: confirmButtonText,
        cancelButtonText: cancelButtonText,
        cancelButtonColor: confirmButtonColor,
        titleStyle: titleStyle!,
        subtitleStyle: subtitleStyle!);
    if (_state != null){
      _state!.update(options);
    } else {
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return Container(
            color: Colors.transparent,
            child: Padding(
              padding: EdgeInsets.all(40.0),
              child: Scaffold(
                backgroundColor: Colors.transparent,
                body: LLSAlertDialog(
                  curve: curve,
                  options: options
                ),
              ),
            ),
          );
        }
      );
    }
  }
}