import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import 'package:markdown/markdown.dart' as md;
import '../module/browser/view.dart';

class GraduallyMdText extends StatefulWidget {
  const GraduallyMdText({
    super.key,
    this.initTxt,
    this.graduallyController,
    this.textStyle,
  });

  final TextStyle? textStyle;
  final GraduallyController? graduallyController;
  final String? initTxt;

  @override
  State<GraduallyMdText> createState() => _GraduallyMdTextState();
}

typedef GraduallyTxtListener = void Function(String txt);

class GraduallyController {
  String graduallyTxt = '';
  int progressIndex = 0;
  Timer? appendTimer;
  bool? isAppendDone;
  bool? isShowDone;

  GraduallyTxtListener? listener;
  VoidCallback? finishedListener;

  setGraduallyTxtListener(GraduallyTxtListener listener) {
    this.listener = listener;
  }

  setGraduallyFinishedListener(VoidCallback finishedListener) {
    this.finishedListener = finishedListener;
  }

  append(String txt) {
    graduallyTxt += txt;
    _startAppend();
  }

  void _initAppend() {
    progressIndex = 0;
    isAppendDone = null;
    isShowDone = null;
    appendTimer = null;
  }

  appendDone() {
    isAppendDone = true;
    // debugPrint('GraduallyMdText: appendDone');
  }

  _startAppend() {
    if (appendTimer != null) {
      return;
    }
    _initAppend();
    appendTimer = Timer.periodic(const Duration(milliseconds: 50), (timer) {
      // debugPrint('GraduallyMdText-progressIndex: $progressIndex');
      if (progressIndex < graduallyTxt.length) {
        progressIndex += 1;
        listener?.call(graduallyTxt.substring(0, progressIndex));
      } else if (isAppendDone == true) {
        // debugPrint('GraduallyMdText: appendTimer done');
        dispose();
        finishedListener?.call();
      }
    });
  }

  dispose() {
    appendTimer?.cancel();
    isAppendDone = null;
    isShowDone = true;
    appendTimer = null;
  }
}

class _GraduallyMdTextState extends State<GraduallyMdText> {
  String mdTxt = '';

  @override
  void initState() {
    super.initState();
    mdTxt = widget.initTxt ?? '';
    widget.graduallyController?.setGraduallyTxtListener((txt) {
      if (mounted) {
        setState(() {
          mdTxt = txt;
        });
      }
    });
  }

  @override
  void dispose() {
    super.dispose();
    // debugPrint('GraduallyMdText-dispose');
    // widget.graduallyController?.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SelectionArea(
      child: HtmlWidget(
        onTapUrl: (url) {
          BrowserPage.start(url);
          return true;
        },
        md.markdownToHtml(mdTxt, inlineSyntaxes: [
          md.InlineHtmlSyntax(),
          md.StrikethroughSyntax(),
          md.EmojiSyntax(),
          md.ColorSwatchSyntax(),
          md.AutolinkExtensionSyntax(),
          md.ImageSyntax()
        ], blockSyntaxes: [
          const md.FencedCodeBlockSyntax(),
          const md.HeaderWithIdSyntax(),
          const md.SetextHeaderWithIdSyntax(),
          const md.UnorderedListWithCheckboxSyntax(),
          const md.OrderedListWithCheckboxSyntax(),
          const md.FootnoteDefSyntax(),
          const md.AlertBlockSyntax(),
        ]),
        textStyle: widget.textStyle,
      ),
    );
  }
}
