import 'dart:async';
import 'dart:convert';
import 'dart:math';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sport/bean/message.dart';
import 'package:sport/bean/post.dart';
import 'package:sport/bean/post_user.dart';
import 'package:sport/db/message_db.dart';
import 'package:sport/pages/social/post_detail_page.dart';
import 'package:sport/pages/social/share_webview.dart';
import 'package:sport/pages/social/user_detail_page.dart';
import 'package:sport/provider/lib/view_state_model.dart';
import 'package:sport/provider/message_model.dart';
import 'package:sport/provider/user_model.dart';
import 'package:sport/router/navigator_util.dart';
import 'package:sport/services/api/inject_api.dart';
import 'package:sport/services/api/resp.dart';
import 'package:sport/services/userid.dart';
import 'package:sport/utils/print_map.dart';
import 'package:sport/utils/toast.dart';
import 'package:sport/widgets/appbar.dart';
import 'package:sport/widgets/decoration.dart';
import 'package:sport/widgets/loading.dart';
import 'package:sport/widgets/menu_bar.dart';
import 'package:sport/widgets/space.dart';
import 'package:sport/widgets/dialog/popupmenu.dart' as menu;
import 'package:provider/provider.dart';

final List<String> avatarList = [
  "https://wx3.sinaimg.cn/mw1024/a6bdcd78gy1gfna8yznv5j20m90m9tbz.jpg",
  "https://wx2.sinaimg.cn/mw1024/a6bdcd78gy1gfna8x3nbzj20m90m943a.jpg",
  "https://wx3.sinaimg.cn/mw1024/a6bdcd78gy1gfnaavrha3j20m90m9dkj.jpg",
  "https://wx4.sinaimg.cn/mw1024/a6bdcd78gy1gfna8znb76j20m90m978t.jpg",
  "https://wx4.sinaimg.cn/mw1024/a6bdcd78gy1gfna8wnwquj20lr0lradp.jpg",
  "https://wx4.sinaimg.cn/mw1024/a6bdcd78gy1gfna90vpgkj20lr0lrtby.jpg",
  "https://wx1.sinaimg.cn/mw1024/a6bdcd78gy1gfna8y4jb6j20m90m9tcj.jpg",
  "https://wx3.sinaimg.cn/mw1024/a6bdcd78gy1gfnaawemhtj20m90m9q7n.jpg",
  "https://wx4.sinaimg.cn/mw1024/a6bdcd78gy1gfnaaveqmwj20ls0lsn07.jpg",
  "https://wxt.sinaimg.cn/mw1024/a6bdcd78gy1gfnaat7uw5j20ls0lr0w0.jpg",
  "https://wx2.sinaimg.cn/mw1024/a6bdcd78gy1gfnaaubdhhj20m90m9786.jpg",
];

class ChatPage extends StatefulWidget {
  final String userName;
  final int userId;
  final Post post;

  ChatPage(this.userName, this.userId, {this.post});

  @override
  State<StatefulWidget> createState() => _ChatPageState();
}

// 服务端的数据 只有 拿了  和 没拿 ，客户端 就是 读了 和没读 ...
class _ChatPageState extends State<ChatPage>
    with InjectLoginApi, InjectApi, UserId, WidgetsBindingObserver {
  GetMenuController _menuController = new GetMenuController();

  StreamSubscription _streamSubscription;
  List<MessageItem> messageList = [];

  GlobalKey SCROLLVIEW = new GlobalKey();

  dispose() {
    super.dispose();
    _streamSubscription?.cancel();
  }

  initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this); // 监听一手自己...
    initMessageList();
    initListen(); // 开启监听... 先试试...
    addPost(); // 这里是分享过来的 ...
//    initScrollBottom();
//    print("${Provider.of<UserModel>(context, listen: false).user.toJson()}");
  }

  // 这个是初始化 聊天列表的...
  initMessageList() async {
//    List<MessageItem> messageList = [];
    List<MessageItem> data = [];
    var list = await MessageDB().getMessageForUserId(widget.userId);
    for (var item in list) {
      MessageItem _item = MessageItem.fromJson(item);
      data.add(_item);
    }
    // 读过就操作一手...
    await MessageDB().updateStatus(widget.userId);

//    messageList.addAll(data);
    data.forEach((element) {
      messageList.insert(0, element);
    });

    // 这里每次都会 拿最新的 而不是添加...
    setState(() {
      messageList = messageList;
    });
  }

  Future addPost() async {
    if (widget.post != null) {
      // 拿到后还得 存
      MessageInstance _instance = (await api.shareForwardSubject(
              int.parse(widget.post.id), widget.userId))
          .data;

      await MessageDB().insert(new MessageItem(
          message: _instance, status: 0, curId: 0, userId: widget.userId));

      addMessageToPage(_instance);
    }
  }

  // 在本页中如果收到了就 ...
  initListen() {
    Stream<List<MessageInstance>> queryStream =
        Provider.of<MessageModel>(context, listen: false).queryStream;
    _streamSubscription =
        queryStream.listen((List<MessageInstance> list) async {
      for (MessageInstance item in list) {
        addMessageToPage(item);
      }
      await MessageDB().updateStatus(widget.userId);
    });
  }
//
//  initScrollBottom() {
//    _timer = Timer(Duration.zero, () {
//      _menuController.scrollToBottom(context, SCROLLVIEW, true);
//    });
//  }

  MessageItem instanceToItem(MessageInstance _instance) {
    int id = _instance.fromUser.id == int.parse(selfId)
        ? _instance.toUser.id
        : _instance.fromUser.id;

    // 里面收到 直接已读... 好像curId 可以不加 status 也可以不写 ...
    MessageItem item =
        new MessageItem(message: _instance, curId: 0, status: 0, userId: id);
    return item;
  }

  // 各种来自别的地方收到的消息 输出到 页面上
  addMessageToPage(MessageInstance _instance) {
    MessageItem item = instanceToItem(_instance);
    messageList.insert(0, item);
//    messageList.add(item);
//    messageList.insert(0, item); // 到头插...
    setState(() {
      messageList = messageList;
    });
  }

//  @override
//  void didChangeMetrics() {
//    super.didChangeMetrics();
//    WidgetsBinding.instance.addPostFrameCallback((_) {
//      // 当前是安卓系统并且在焦点聚焦的情况下
////      _menuController.scrollToBottom();
//    });
//  }

// 封装的聊天msg
// @who  判断是用户自己的还是 聊的那个人
// @msg  信息 聊天的那个
// @type 聊天的类型 可能是通过分享过来的那种 ? 游戏 或者是 别的 社区 或者是 链接 ?

  Widget _buildChatItem(MessageItem item) {
    GlobalKey anchorKey = GlobalKey();

    MessageInstance data = item.message;

    int who = data.fromUser.id ==
            Provider.of<UserModel>(context, listen: false).user.id
        ? 1
        : 0;

    String userAvatar = data.fromUser.avatar;

    Widget chatItemOfType(String type) {
      // 文本或者是图片...
      if (type == "text" || type == "image") {
        return Column(
          children: <Widget>[
            if (data.data.text != null)
              Text(
                "${data.data.text}",
                style: Theme.of(context)
                    .textTheme
                    .subtitle1
                    .copyWith(fontSize: 16, color: Colors.black),
                key: anchorKey,
              ),
            if (data.data.url != null)
              CachedNetworkImage(imageUrl: data.data.url)
//            SizedBox(
//              height: 10.0,
//            ),
//          if (imageUrls?.length != null)
//            GridView.count(
//                physics: new NeverScrollableScrollPhysics(),
//                shrinkWrap: true,
//                padding: EdgeInsets.zero,
//                crossAxisSpacing: 10.0,
//                crossAxisCount: imageUrls.length > 3 ? 3 : imageUrls.length,
//                mainAxisSpacing: 10.0,
//                children: imageUrls
//                    .asMap()
//                    .keys
//                    .map((i) => CachedNetworkImage(
//                          imageUrl: imageUrls[i],
//                          fit: BoxFit.cover,
//                        ))
//                    .toList())
          ],
          crossAxisAlignment: CrossAxisAlignment.start,
        );
      }
      // 论坛消息 ...
      if (type == "forum-forward") {
        return InkWell(
          child: Column(
            children: <Widget>[
              RichText(
                text: TextSpan(children: [
                  TextSpan(
                      text: data.data.user.name,
                      style: Theme.of(context)
                          .textTheme
                          .headline6
                          .copyWith(color: Color(0xFFFFC400))),
                  TextSpan(
                      text: data.data.subject.content,
                      style: Theme.of(context).textTheme.subtitle1),
                ]),
              ),
              Space(
                height: 5.0,
              ),
              if (data.data.subject.images.length > 0)
                GridView.count(
                    physics: new NeverScrollableScrollPhysics(),
                    shrinkWrap: true,
                    padding: EdgeInsets.zero,
                    crossAxisSpacing: 10.0,
                    crossAxisCount: data.data.subject.images.length > 3
                        ? 3
                        : data.data.subject.images.length,
                    mainAxisSpacing: 10.0,
                    childAspectRatio: 9 / 6,
                    children: data.data.subject.images
                        .asMap()
                        .keys
                        .map(
                          (i) => CachedNetworkImage(
                            alignment: Alignment.centerLeft,
                            imageUrl: data.data.subject.images[i],
                            fit: BoxFit.cover,
//                        width: data.data.subject.images[i]
                          ),
                        )
                        .toList()),
              Divider(),
              Row(
                children: <Widget>[
                  Container(
                    width: 20.0,
                    height: 20.0,
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(6),
                      child: CachedNetworkImage(
                        imageUrl: data.data.forum.cover,
                      ),
                    ),
                  ),
                  Space(
                    width: 5,
                  ),
                  Text(
                    data.data.forum.name,
                  )
                ],
              )
            ],
          ),
          onTap: () async {
            Post post =
                (await api.getPostDetail("${data.data.subject.id}")).data;
            print(post);
            NavigatorUtil.goPage(
                context, (context) => PostDetailPage(post, false, null));
          },
        );
      }
      // 链接..
      if (type == "link") {
        return InkWell(
            child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
              CachedNetworkImage(
                imageUrl: data.data.logo,
                width: 60.0,
                height: 60.0,
              ),
              Space(
                width: 5.0,
              ),
              Expanded(
                child: RichText(
                  text: TextSpan(children: [
                    TextSpan(
                        text: data.data.user.name,
                        style: Theme.of(context)
                            .textTheme
                            .headline6
                            .copyWith(color: Color(0xFFFFC400))),
                    TextSpan(
                        text: data.data.text,
                        style: Theme.of(context).textTheme.subtitle1),
                  ]),
                ),
              )
            ]),
          onTap: () async{
              await NavigatorUtil.goPage(context, (context) => WebViewSharePage(data.data.url));
          },
        );
      }
    }

    Widget customPoint = CustomPaint(
        painter: who == 1 ? _BubblePainterRight() : _BubblePainter(),
        child: ConstrainedBox(
          constraints:
              BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.6),
          child: Container(
              padding: who == 1
                  ? EdgeInsets.fromLTRB(12, 6, 20, 8)
                  : EdgeInsets.fromLTRB(20, 6, 12, 8),
              child: GestureDetector(
                  onLongPressStart: (e) {
                    RenderBox renderBox =
                        anchorKey.currentContext.findRenderObject();
                    var offset = renderBox
                        .localToGlobal(Offset(0.0, renderBox.size.height));
                    final RelativeRect position = RelativeRect.fromLTRB(
                        e.globalPosition.dx, //取点击位置坐弹出x坐标
                        offset.dy, //取text高度做弹出y坐标（这样弹出就不会遮挡文本）
                        e.globalPosition.dx,
                        offset.dy);

                    PopupMenuEntry menuItem(
                            {String imgUrl, String text, Function callBack}) =>
                        menu.PopupMenuItem(
                          child: InkWell(
                            onTap: () {
                              callBack();
                              Navigator.pop(context);
                            },
                            child: Row(
                              mainAxisSize: MainAxisSize.min,
                              children: <Widget>[
                                Image.asset(
                                  "lib/assets/img/$imgUrl",
                                  width: 24,
                                ),
                                SizedBox(
                                  width: 4,
                                ),
                                Text(
                                  text,
                                )
                              ],
                            ),
                          ),
                        );

                    showMenu(
                      context: context,
                      position: position,
                      items: <PopupMenuEntry>[
                        PopupMenuItem(
                            child: Container(
                          child: Column(
                            children: <Widget>[
                              menuItem(
                                  imgUrl: "linkpop_icon_copy.png",
                                  text: "复制",
                                  callBack: () {
                                    Clipboard.setData(ClipboardData(
                                        text: '${data.data.text}'));
                                    ToastUtil.show("复制成功");
                                  }),
                              who == 1
                                  ? menuItem(
                                      imgUrl: "linkpop_icon_del.png",
                                      text: "删除")
                                  : menuItem(
                                      imgUrl: "linkpop_icon_modify_1.png",
                                      text: "举报"),
                              menuItem(
                                  imgUrl: "linkpop_icon_cancel.png", text: "取消")
                            ],
                          ),
                        ))
                      ],
                    );
                  },
                  child: chatItemOfType(data.type))),
        ));

    Widget spaceItem = Space(
      width: 12,
    );

    Widget avatar = InkWell(
      onTap: () async {
        await NavigatorUtil.goPage(
            context,
            (context) => UserDetailPage(PostUser(
                id: "${data.fromUser?.id}",
                name: data.fromUser?.name,
                avatar: data.fromUser?.id == selfId
                    ? Provider.of<UserModel>(context, listen: false).user.avatar
                    : data.fromUser.avatar)));
      },
      child: CircleAvatar(
        backgroundImage: CachedNetworkImageProvider(userAvatar),
        radius: 20,
      ),
    );

    List<Widget> chatContentUsr = [customPoint, spaceItem, avatar];

    List<Widget> chatContentOther = [avatar, spaceItem, customPoint];

    return Padding(
        padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
        child: Row(
          mainAxisAlignment:
              who == 1 ? MainAxisAlignment.end : MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: who == 1 ? chatContentUsr : chatContentOther,
        ));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(
            "${widget.userName}",
            style: titleStyle,
          ),
          leading: buildBackButton(context),
        ),
        resizeToAvoidBottomInset: false, // 透传MediaQuery 的高度？
        body: MenuBar(
          CustomScrollView(
            key: SCROLLVIEW,
            reverse: true,
            controller: _menuController.scrollMenuController,
            slivers: <Widget>[
              if (messageList?.length == 0)
                SliverToBoxAdapter(
                  child: Container(),
                ),
              if (messageList?.length != 0)
                SliverList(
                  delegate: SliverChildBuilderDelegate((content, index) {
//                    MessageInstance data = messageList[index];
                    return _buildChatItem(messageList[index]);
                  }, childCount: messageList.length),
                ),
            ],
          ),
          menuIdentity:
              new MenuIdentity(menuScene: "chat", userId: widget.userId),
          inputField: "",
//          scrollToBottom: _menuController.scrollToBottom, // 暂时可以废弃...
          sendCallBack: addMessageToPage,
          globalkey: SCROLLVIEW,
        ));
  }
}

class _BubblePainter extends CustomPainter {
  final circular = Radius.circular(10);
  final Paint _paint = Paint()..color = Colors.white;
  final double _bubbleWidth = 10;

  @override
  void paint(Canvas canvas, Size size) {
//    Path path = Path()..moveTo(size.width,  size.height / 2)..quadraticBezierTo(size.width / 3*2, size.height / 2 + 50, 0, size.height / 2)
//    ..quadraticBezierTo(size.width / 3, size.height,size.width,size.height)..close();
    Path path = Path()
      ..moveTo(_bubbleWidth + 1, _bubbleWidth)
      ..quadraticBezierTo(
          _bubbleWidth / 3 * 2, _bubbleWidth + 4, 0, _bubbleWidth)
      ..quadraticBezierTo(_bubbleWidth / 3, _bubbleWidth + _bubbleWidth / 2,
          _bubbleWidth + 1, _bubbleWidth * 2)
      ..close();
    canvas.drawPath(path, _paint);
    canvas.drawRRect(
        RRect.fromLTRBR(_bubbleWidth, 0, size.width, size.height, circular),
        _paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}

class _BubblePainterRight extends CustomPainter {
  final circular = Radius.circular(10);
  final Paint _paint = Paint()..color = Colors.white;
  final double _bubbleWidth = 10;

  @override
  void paint(Canvas canvas, Size size) {
//    Path path = Path()..moveTo(size.width,  size.height / 2)..quadraticBezierTo(size.width / 3*2, size.height / 2 + 50, 0, size.height / 2)
//    ..quadraticBezierTo(size.width / 3, size.height,size.width,size.height)..close();
    double left = size.width - _bubbleWidth;
    Path path = Path()
      ..moveTo(left, _bubbleWidth)
      ..quadraticBezierTo(left + _bubbleWidth / 3 * 2, _bubbleWidth + 2,
          size.width, _bubbleWidth)
      ..quadraticBezierTo(left + _bubbleWidth / 3,
          _bubbleWidth + _bubbleWidth / 2, left, _bubbleWidth * 2)
      ..close();
    canvas.drawPath(path, _paint);
    canvas.drawRRect(
        RRect.fromLTRBR(0, 0, size.width - _bubbleWidth, size.height, circular),
        _paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}
