import 'package:better_open_file/better_open_file.dart';
import 'package:bubble/bubble.dart';
import 'package:flowder/flowder.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:jiffy/jiffy.dart';

import '../../../api/marianumcloud/talk/chat/getChatResponse.dart';
import '../../../api/marianumcloud/talk/room/getRoomResponse.dart';
import '../../../theming/appTheme.dart';
import '../../../widget/debug/debugTile.dart';
import '../files/fileElement.dart';
import 'chatMessage.dart';

class ChatBubble extends StatefulWidget {
  final BuildContext context;
  final bool isSender;
  final GetChatResponseObject bubbleData;
  final GetRoomResponseObject chatData;

  const ChatBubble({
    required this.context,
    required this.isSender,
    required this.bubbleData,
    required this.chatData,
    Key? key}) : super(key: key);

  @override
  State<ChatBubble> createState() => _ChatBubbleState();
}

class _ChatBubbleState extends State<ChatBubble> {
  BubbleStyle getSystemStyle() {
    return BubbleStyle(
      color: AppTheme.isDarkMode(context) ? const Color(0xff182229) : Colors.white,
      borderWidth: 1,
      elevation: 2,
      margin: const BubbleEdges.only(bottom: 20, top: 10),
      alignment: Alignment.center,
    );
  }

  BubbleStyle getRemoteStyle(bool seamless) {
    var color = AppTheme.isDarkMode(context) ? const Color(0xff202c33) : Colors.white;
    return BubbleStyle(
      nip: BubbleNip.leftTop,
      color: seamless ? Colors.transparent : color,
      borderWidth: seamless ? 0 : 1,
      elevation: seamless ? 0 : 1,
      margin: const BubbleEdges.only(bottom: 10, left: 10, right: 50),
      alignment: Alignment.topLeft,
    );
  }

  BubbleStyle getSelfStyle(bool seamless) {
    return BubbleStyle(
      nip: BubbleNip.rightBottom,
      color: seamless ? Colors.transparent : const Color(0xff005c4b),
      borderWidth: seamless ? 0 : 1,
      elevation: seamless ? 0 : 1,
      margin: const BubbleEdges.only(bottom: 10, right: 10, left: 50),
      alignment: Alignment.topRight,
    );
  }

  late ChatMessage message;
  double downloadProgress = 0;
  Future<DownloaderCore>? downloadCore;

  Size _textSize(String text, TextStyle style) {
    final TextPainter textPainter = TextPainter(
        text: TextSpan(text: text, style: style),
        maxLines: 1,
        textDirection: TextDirection.ltr)
      ..layout(minWidth: 0, maxWidth: double.infinity);
    return textPainter.size;
  }

  BubbleStyle getStyle() {
    if(widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment) {
      if(widget.isSender) {
        return getSelfStyle(message.containsFile);
      } else {
        return getRemoteStyle(message.containsFile);
      }
    } else {
      return getSystemStyle();
    }
  }


  @override
  Widget build(BuildContext context) {
    message = ChatMessage(originalMessage: widget.bubbleData.message, originalData: widget.bubbleData.messageParameters);
    bool showActorDisplayName = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne;
    bool showBubbleTime = widget.bubbleData.messageType != GetRoomResponseObjectMessageType.system;
    var actorTextStyle = TextStyle(color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold);

    return GestureDetector(
      child: Bubble(

        style: getStyle(),
        child: Container(
          constraints: BoxConstraints(
            maxWidth: MediaQuery.of(context).size.width * 0.9,
            minWidth: showActorDisplayName ? _textSize(widget.bubbleData.actorDisplayName, actorTextStyle).width : 30,
          ),
          child: Stack(
            children: [
              Padding(
                  padding: EdgeInsets.only(bottom: showBubbleTime ? 18 : 0, top: showActorDisplayName ? 18 : 0),
                  child: FutureBuilder(
                    future: message.getWidget(),
                    builder: (context, snapshot) {
                      if(!snapshot.hasData) return const CircularProgressIndicator();
                      return snapshot.data ?? const Icon(Icons.error);
                    },
                  )
              ),
              Visibility(
                visible: showActorDisplayName,
                child: Positioned(
                  top: 0,
                  left: 0,
                  child: Text(
                    widget.bubbleData.actorDisplayName,
                    textAlign: TextAlign.start,
                    style: actorTextStyle,
                  ),
                ),
              ),
              Visibility(
                visible: showBubbleTime,
                child: Positioned(
                  bottom: 0,
                  right: 0,
                  child: Text(
                    Jiffy.parseFromMillisecondsSinceEpoch(widget.bubbleData.timestamp * 1000).format(pattern: "HH:mm"),
                    textAlign: TextAlign.end,
                    style: const TextStyle(color: Colors.grey, fontSize: 12),
                  ),
                ),
              ),
              Visibility(
                visible: downloadProgress > 0,
                child: Positioned(
                  top: 0,
                  left: 0,
                  right: 0,
                  bottom: 0,
                  child: Stack(
                    children: [
                      const Center(child: Icon(Icons.download)),
                      const Center(child: CircularProgressIndicator(color: Colors.white)),
                      Center(child: CircularProgressIndicator(value: downloadProgress/100)),
                    ],
                  )
                ),
              ),
            ],
          ),
        ),
      ),
      onLongPress: () {
        showDialog(context: context, builder: (context) {
          return SimpleDialog(
            children: [
              Visibility(
                visible: !message.containsFile && widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment,
                child: ListTile(
                  leading: const Icon(Icons.copy),
                  title: const Text("Nachricht kopieren"),
                  onTap: () => {
                    Clipboard.setData(ClipboardData(text: widget.bubbleData.message)),
                    Navigator.of(context).pop(),
                  },
                ),
              ),
              Visibility(
                visible: !widget.isSender && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne,
                child: ListTile(
                  leading: const Icon(Icons.sms_outlined),
                  title: Text("Private Nachricht an '${widget.bubbleData.actorDisplayName}'"),
                  onTap: () => {},
                ),
              ),
              DebugTile(widget.bubbleData.toJson()).asTile(context),
            ],
          );
        });
      },
      onTap: () {
        if(message.file == null) return;

        if(downloadProgress > 0) {
          showDialog(context: context, builder: (context) {
            return AlertDialog(
              title: const Text("Download abbrechen?"),
              content: const Text("Möchtest du den Download abbrechen?"),
              actions: [
                TextButton(onPressed: () {
                  Navigator.of(context).pop();
                }, child: const Text("Nein")),
                TextButton(onPressed: () {
                  downloadCore?.then((value) {
                    if(!value.isCancelled) value.cancel();
                    Navigator.of(context).pop();
                  });
                  setState(() {
                    downloadProgress = 0;
                    downloadCore = null;
                  });
                }, child: const Text("Ja, Abbrechen"))
              ],
            );
          });

          return;
        }

        downloadProgress = 1;
        downloadCore = FileElement.download(message.file!.path!, message.file!.name, (progress) {
          if(progress > 1) {
            setState(() {
              downloadProgress = progress;
            });
          }
        }, (result) {
          setState(() {
            downloadProgress = 0;
          });

          if(result.type != ResultType.done) {
            showDialog(context: context, builder: (context) {
              return AlertDialog(
                content: Text(result.message),
              );
            });
          }
        });
      },
    );
  }
}