import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:chat/chat/download_item.dart';
import 'package:chat/chat/file_msg_item.dart';
import 'package:chat/chat/gift_msg_item.dart';
import 'package:chat/chat/msg_state_widge.dart';
import 'package:chat/chat/place_item.dart';
import 'package:chat/chat/redbag_widget.dart';
import 'package:chat/chat/upload_item.dart';
import 'package:chat/chat/video_view.dart';
import 'package:chat/data/UserData.dart';
import 'package:chat/data/constants.dart';
import 'package:chat/generated/i18n.dart';
import 'package:chat/models/ChatMsg.dart';
import 'package:chat/models/UserInfo.dart';
import 'package:chat/models/group_info_model.dart';
import 'package:chat/models/keyboard_provider.dart';
import 'package:chat/models/ref_name_provider.dart';
import 'package:chat/proto/chat.pbenum.dart';
import 'package:chat/proto/chat.pbserver.dart';
import 'package:chat/proto/transhousekeeper.pb.dart';
import 'package:chat/utils/CustomUI.dart';
import 'package:chat/utils/HttpUtil.dart';
import 'package:chat/utils/MessageMgr.dart';
import 'package:chat/utils/app_navigator.dart';
import 'package:chat/utils/date_utils.dart';
import 'package:chat/utils/file_cache_mgr.dart';
import 'package:chat/utils/msgHandler.dart';
import 'package:chat/utils/screen.dart';
import 'package:chat/utils/sound_util.dart';
import 'package:chat/utils/upload_util.dart';
import 'package:chat/utils/video_anim.dart';
import 'package:chat/utils/wpop/w_popup_menu.dart';
import 'package:dio/dio.dart';
import 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oktoast/oktoast.dart';
import 'package:provider/provider.dart';
import 'package:share_extend/share_extend.dart';
import 'package:url_launcher/url_launcher.dart';

import '../r.dart';
import 'full_img_view.dart';
import 'upload_item.dart';
import 'package:chat/models/money_change.dart';
import 'package:chat/models/voucher_change.dart';

const double ChatRadius = 7.5;
const Color SendMsgBg = Color(0xFFD4F0FF);

const double TextHeight = 1.2;

const double PaddingLeft = 9.5;

const Color ReciveBorderColor = Color(0xFFDCDCDC);

const double FontSize = 15;

class ChatPageItem extends StatefulWidget {
  final MsgModel msg;

  final UserInfo friendInfo;
  final int lastMsgTime;

  final Function hideKeyboard;

  const ChatPageItem(
      {Key key, this.msg, this.lastMsgTime, this.friendInfo, this.hideKeyboard})
      : assert(msg != null),
        super(key: key);

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

class _ChatPageItemState extends State<ChatPageItem>
    with SingleTickerProviderStateMixin {
  int curTextType = 0; //文字、译文切换索引
  List<String> textList = [];

  UserInfo friendInfo;

  String curSoundUrl;

  CancelToken _cancelToken = CancelToken();

  bool isLongPressed = false;

  double maxWidth = Screen.width - 140;
  @override
  void initState() {
    super.initState();
    friendInfo = widget.friendInfo;

    if (widget.msg.from == UserData().basicInfo.userId &&
        widget.msg.state == MsgState.None) {
      print('重新发送消息');
      MsgHandler.sendChatMsg(widget.msg);
    }

    textList = widget.msg.getTransTextList();

    MessageMgr().on('Update Translate Message', updateTranslateMsg);
    MessageMgr().on('Cancel Request', _deleteItem);

    MessageMgr().on('Cancel Request', _deleteItem);
  }

  @override
  void dispose() {
    MessageMgr().off('Cancel Request', _deleteItem);
    MessageMgr().off('Update Translate Message', updateTranslateMsg);
    super.dispose();
  }

  _deleteItem(msg) {
    if (msg == widget.msg) {
      print(widget.msg.state);
      if (widget.msg.state == MsgState.Uploading) {
        print('取消上传');
        UploadUtil().cancelRequests(_cancelToken);
      }
    }
  }

  updateTextList() {
    textList.clear();
    curTextType = 0;
    textList = widget.msg.getTransTextList();
  }

  updateTranslateMsg(msg) {
    if (msg.time == widget.msg.time) {
      if (mounted) {
        updateTextList();
        if (!mounted) {
          return;
        }
        setState(() {
          print('更新翻译文字');
        });
      }
    }
  }

  getTodayTime(msgDate, {var sendTime}) {
    String showTimeStr;

    sendTime = sendTime ?? widget.msg.time;
    var today = DateTime.now();
    //今天
    if (msgDate.year == today.year &&
        msgDate.month == today.month &&
        msgDate.day == today.day) {
      showTimeStr =
          DateUtils().getFormartData(timeSamp: sendTime, format: 'HH:mm');
    } else {
      showTimeStr = DateUtils()
          .getFormartData(timeSamp: sendTime, format: 'yyyy/MM/dd HH:mm');
    }

    return showTimeStr;
  }

  String getMsgTime() {
    String showTimeStr;

    var sendTime = widget.msg.time;

    var msgDate = DateTime.fromMillisecondsSinceEpoch(sendTime);
    if (widget.lastMsgTime == null) {
      showTimeStr = getTodayTime(msgDate);
    } else {
      if (sendTime - widget.lastMsgTime > 3 * 60 * 1000) {
        showTimeStr = getTodayTime(msgDate);
      }
    }

    return showTimeStr;
  }

  @override
  Widget build(BuildContext context) {
    var showTime = getMsgTime();

    return Container(
      width: Screen.width,
      margin: const EdgeInsets.symmetric(vertical: 18.0,horizontal: 8),
      child: Column(
        children: <Widget>[
          showTime == null
              ? SizedBox()
              : Container(
                  decoration: BoxDecoration(
                      color: Color(0xFF2C2F36).withOpacity(0.25),
                      borderRadius: BorderRadius.all(Radius.circular(9.5))),
                  padding:
                      EdgeInsets.only(left: 7, right: 7, top: 3, bottom: 2),
                  child: Text(showTime,
                      textScaleFactor: 1.0,
                      style: TextStyle(fontSize: 10.0, color: Colors.white)),
                ),
          SizedBox(height: 10),
          _msgWidget()
        ],
      ),
    );
  }

  _msgWidget() {
    if (widget.msg.from == 0) {
      return _serverNotifyMsg();
    } else {
      if (widget.msg.from == UserData().basicInfo.userId) {
        return _getSentMessageLayout(context);
      } else {
        return _getReceivedMessageLayout(context);
      }
    }
  }

  _serverNotifyMsg() {
    var type = widget.msg.msgType;

    if (type == ChatType.RedWalletChatType.value) {
      RedWallet wallet = RedWallet.fromBuffer(widget.msg.msgContent);

      var msg = '';

      if (wallet.state == RedWalletState.Received) {
        if (wallet.tuId == friendInfo.userId) {
          msg = I18n.of(context).get_money.replaceFirst(
              '/s1',
              Provider.of<RefNameProvider>(context)
                  .getRefName(friendInfo.userId, friendInfo.nickName));
        } else {
          msg = I18n.of(context).you_get_money.replaceFirst(
              '/s1',
              Provider.of<RefNameProvider>(context)
                  .getRefName(friendInfo.userId, friendInfo.nickName));
        }
      } else {
        if (wallet.tuId == friendInfo.userId) {
          msg = I18n.of(context).your_redMoney_over;
        } else {
          msg = I18n.of(context).other_redMoney_over;
        }
      }

      return Container(
        alignment: Alignment.center,
        constraints: BoxConstraints(maxWidth: Screen.width - 120),
        child: extendedText(msg, color: Constants.GreyTextColor, fontSize: 12),
      );
    } else {
      ///todo 翻译管家系统通知消息

      print('这里应该要有翻译管家');
      if (type == ChatType.GroupChatNoticeType.value && widget.msg.channelType ==ChatChannelType.Session.value) {
        TransHKChatNotice res = TransHKChatNotice.fromBuffer(widget.msg.msgContent);

        if(res.noticeType==TransHKChatNoticeType.StartChat){
          ///开始翻译服务
          return _buildServiceCard(true, () {});
        }else  if(res.noticeType==TransHKChatNoticeType.EndChat){
          ///翻译服务结束
          return _buildServiceCard(false, () {});
        }else{
          return Container();
        }
//        return Container();

      }
//      else{
//        if (type == ChatType.GroupChatNoticeType.value) {
//          var res = GroupChatNotice.fromBuffer(widget.msg.msgContent);
//
//          var groupInfoModel = Provider.of<GroupInfoModel>(context);
//          var showStr = MsgHandler.getGroupNoticeMsg(res, groupInfoModel);
//          return Container(
//            alignment: Alignment.center,
//            constraints: BoxConstraints(maxWidth: Screen.width - 120),
//            child: Text(
//              showStr,
//              textScaleFactor: 1.0,
//              textAlign: TextAlign.center,
//              style: TextStyle(color: Constants.GreyTextColor, fontSize: 12),
//            ),
//          );
//        }
//      }



    }
    return Container();
  }

  _textGif(List<int> msgContent) {
    var msg = utf8.decode(msgContent);
    return Container(
      constraints: BoxConstraints(maxWidth: Screen.width - 120),
      child: extendedText(
        msg,
        hideKeyboard: widget.hideKeyboard,
        fontSize: FontSize,
        color: Colors.black,
      ),
    );
  }

  _textMsg(List<int> msgContent) {
    List<Widget> showMsg = [];
    var width = 0.0;
    var msg = utf8.decode(msgContent);
    if (msg.contains('[ ')) {
      msg = msg.replaceAll('[ ', '[');
    }
    if (msg.contains(' ]')) {
      msg = msg.replaceAll(' ]', ']');
    }
    bool isUrl = false;
    if (textList[curTextType].contains('http')) {
      isUrl = true;
    }

    if (widget.msg.refMsgContent != null &&
        widget.msg.refMsgContent.length > 0) {
      QuoteMsg quoteMsg = QuoteMsg.fromBuffer(widget.msg.refMsgContent);
      var refName = Provider.of<RefNameProvider>(context)
          .getRefName(friendInfo.userId, friendInfo.nickName);
      var msgDate =
          DateTime.fromMillisecondsSinceEpoch(quoteMsg.sendTime.toInt());
      var showTimeStr = getTodayTime(msgDate, sendTime: quoteMsg.sendTime.toInt());

      var timetWidth = CustomUI.getRealTextWidht(showTimeStr, 13);
      var nameWidhth = CustomUI.getRealTextWidht(refName, 13);
      width = timetWidth + (nameWidhth > 70 ? 70 : nameWidhth) + 36;
      var tempIndex = quoteMsg.content.indexOf(':');
      var quoteContent = tempIndex == -1
          ? quoteMsg.content
          : quoteMsg.content.substring(quoteMsg.content.indexOf(':') + 2);
      var contentWidht = _getTextWidth(quoteContent, fontSize: 13);
      width = min(max(width, contentWidht), maxWidth);
      showMsg.add(InkWell(
          onTap: () {
            MessageMgr().emit('Jump to Msg', quoteMsg.sendTime.toInt());
          },
          child: Container(
            padding: EdgeInsets.all(8),
            margin: EdgeInsets.only(bottom: 5),
            decoration: BoxDecoration(
                color: Color(0xFFC4E0F5),
                borderRadius: BorderRadius.circular(5.5)),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Row(children: <Widget>[
                  Container(
                      constraints: BoxConstraints(maxWidth: 70),
                      child: Text(
                        refName,
                        style: TextStyle(fontSize: 13),
                        overflow: TextOverflow.ellipsis,
                      )),
                  SizedBox(width: 20),
                  Text(
                    showTimeStr,
                    style: TextStyle(fontSize: 13),
                  )
                ]),
                SizedBox(height: 7.5),
                Text(
                  quoteContent,
                  style: TextStyle(fontSize: 13),
                )
              ],
            ),
          )));
    }
    var contentWidth = _getTextWidth(textList[curTextType]);
    if (contentWidth > width && contentWidth <= maxWidth) {
      width = contentWidth;
    }

    showMsg.add(Container(
        constraints: BoxConstraints(maxWidth: maxWidth, minHeight: 22),
        alignment: Alignment.centerLeft,
        child: extendedText(
          textList[curTextType],
          color: isUrl ? Colors.blue : Constants.BlackTextColor,
          hideKeyboard: widget.hideKeyboard,
          fontSize: FontSize,
        )));

    return Container(
      constraints: BoxConstraints(maxWidth: Screen.width - 120),
      width: width + 20,
      child: Column(
          crossAxisAlignment: CrossAxisAlignment.start, children: showMsg),
      padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5),
      decoration: BoxDecoration(
          color: isLongPressed ? Colors.grey[300] : SendMsgBg,
          border: Border.all(color: Color(0xFFB9CBD7), width: 0.6),
          borderRadius: BorderRadius.all(Radius.circular(ChatRadius))),
    );
  }

  _soundMsg() {
    double time = widget.msg.extraInfo / 1000;
    if (time > 60) {
      time = 60.0;
    }
    bool isPlaying = false;

    var soundPath = widget.msg.localFile;

    isPlaying = SoundUtils().isPlaying(soundPath);

    var soundWidget = GestureDetector(
      child: Container(
        width: 120,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Container(
              alignment: Alignment.center,
              padding: EdgeInsets.only(bottom: 2),
              margin: EdgeInsets.only(right: 10),
              width: 25.5,
              height: 25.5,
              decoration: BoxDecoration(
                  border:
                      Border.all(color: const Color(0xFF1B92C7), width: 0.5),
                  color: const Color(0xFF04A4FE),
                  shape: BoxShape.circle),
              child: Icon(
                IconData(isPlaying ? 0xe652 : 0xe653,
                    fontFamily: Constants.IconFontFamily),
                size: isPlaying ? 15 : 18,
                color: Colors.white,
              ),
            ),
            isPlaying
                ? Stack(
                    children: <Widget>[
                      Container(
                        height: 18,
                        width: 19,
                      ),
                      Positioned(
                          bottom: 0,
                          child: VideoAnim(
                            begin: 18,
                            start: 0.444,
                            end: 4.5,
                          )),
                      Positioned(
                          left: 7,
                          bottom: 0,
                          child: VideoAnim(
                            begin: 4.5,
                            end: 18,
                          )),
                      Positioned(
                          left: 14,
                          bottom: 0,
                          child: VideoAnim(
                            begin: 18,
                            end: 4.5,
                          ))
                    ],
                  )
                : Stack(
                    children: <Widget>[
                      Container(
                        height: 18,
                        width: 19,
                      ),
                      Positioned(
                          bottom: 0, child: CustomUI.buildAudioContaniner(12)),
                      Positioned(
                          left: 7,
                          bottom: 0,
                          child: CustomUI.buildAudioContaniner(4.5)),
                      Positioned(
                          left: 14,
                          bottom: 0,
                          child: CustomUI.buildAudioContaniner(18))
                    ],
                  ),
            Expanded(child: SizedBox()),
            fixedText(time.toStringAsFixed(0),
                color: Constants.BlackTextColor, fontSize: 16)
          ],
        ),
        padding: EdgeInsets.symmetric(horizontal: 15, vertical: 12),
        decoration: BoxDecoration(
            color: SendMsgBg,
            border: Border.all(color: Color(0xFFB9CBD7), width: 0.6),
            borderRadius: BorderRadius.all(Radius.circular(ChatRadius))),
      ),
      onTap: () async {
        print('播放状态 : $isPlaying');
        print('当前文件$soundPath ');
        if (isPlaying) {
          SoundUtils().pause();
        } else {
          SoundUtils().play(soundPath, onPlayed: () {
            if (mounted) {
              setState(() {});
            }
          }, complete: () {
            if (mounted) {
              setState(() {});
            }
          });
        }
      },
    );

    return UploadImgItem(
      msg: widget.msg,
      child: soundWidget,
      isShowProgress: false,
    );
  }

  Size _getImgSize() {
    double aspectRatio = widget.msg.extraInfo / 100;

    var maxWidth = Screen.width * 0.65;
    var maxHeight = Screen.height / 4;

    var width, height;
    if (maxWidth / maxHeight > aspectRatio) {
      height = maxHeight;
      width = maxHeight * aspectRatio;
    } else {
      width = maxWidth;
      height = maxWidth / aspectRatio;
    }

    return Size(width, height);
  }

  _imgMsg(List<int> imgData) {
    var imgSize = _getImgSize();
    ImageProvider provider = MemoryImage(widget.msg.localFile == null
        ? Uint8List.fromList(imgData)
        : File(widget.msg.localFile).readAsBytesSync());

    return GestureDetector(
        child: ClipRRect(
          child: UploadImgItem(
              msg: widget.msg,
              cancelToken: _cancelToken,
              child: Container(
                height: imgSize.height,
                width: imgSize.width,
                child: Image(
                  fit: BoxFit.contain,
                  image: provider,
                ),
              )),
          borderRadius: BorderRadius.circular(5),
        ),
        onTap: () async {
          showFullImg(context, widget.msg);
        });
  }

  _videoMsg(BuildContext context, List<int> thumbnail) {
    var imgSize = _getImgSize();
    return InkWell(
      child: ClipRRect(
        child: Stack(
          alignment: Alignment.center,
          children: <Widget>[
            UploadImgItem(
                msg: widget.msg,
                cancelToken: _cancelToken,
                child: Container(
                  width: imgSize.width,
                  height: imgSize.height,
                  child: Image(
                    fit: BoxFit.contain,
                    image: MemoryImage(Uint8List.fromList(thumbnail)),
                  ),
                ))
          ],
        ),
        borderRadius: BorderRadius.circular(5),
      ),
      onTap: () {
        showVideoPage(context, widget.msg.localFile);
      },
    );
  }

  _msgLayout(BuildContext context, MsgModel msg) {
    Widget item;

    switch (ChatType.valueOf(msg.msgType)) {
      case ChatType.TextChatType:
        item = _textMsg(msg.msgContent);
        break;

      case ChatType.EmoticonType:
        item = _textGif(msg.msgContent);
        break;
      case ChatType.ImageChatType:
        item = _imgMsg(msg.msgContent);
        break;
      case ChatType.ShortVideoChatType:
        item = _videoMsg(context, msg.msgContent);
        break;
      case ChatType.ShortVoiceChatType:
        item = _soundMsg();
        break;
      case ChatType.RedWalletChatType:
        item = RedBagItem(
            Key(msg.time.toString()), UserData().basicInfo.userId, msg);
        break;
      case ChatType.PlaceChatType:
        item = PlaceItem(isMe: true, placeContent: msg.msgContent);
        break;
      case ChatType.GiftChatType:
        item = GiftMsgItem(msg.msgContent, true);
        break;
      case ChatType.FileChatType:
        item = _fileMsgItem();
        break;
      default:
    }

    return wrapItemWithMenu(item);
  }

  Widget _fileMsgItem() {
    return UploadImgItem(
        msg: widget.msg,
        cancelToken: _cancelToken,
        child: Container(
            height: 100,
            constraints: BoxConstraints(maxWidth: Screen.width - 120),
            padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5),
            decoration: BoxDecoration(
                color: isLongPressed ? Colors.grey[300] : SendMsgBg,
                borderRadius: BorderRadius.all(Radius.circular(ChatRadius))),
            child: FileMsgItem(widget.msg)));
  }

  Widget _getSentMessageLayout(BuildContext context) {
    bool hasHeadImg = true;
    if (UserData().basicInfo.headimgurl == null ||
        UserData().basicInfo.headimgurl.length == 0) {
      hasHeadImg = false;
    }
    return Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          MsgStateWidget(widget.msg),
          SizedBox(width: 3),
          _msgLayout(context, widget.msg),
          SizedBox(width: 10),
          Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: <Widget>[
              ClipRRect(
                  borderRadius: BorderRadius.circular(8),
                  child: hasHeadImg
                      ? CachedNetworkImage(
                          imageUrl: UserData().basicInfo.headimgurl,
                          placeholder: (context, url) => Image.asset(
                            Constants.DefaultHeadImgUrl,
                            width: 40,
                            height: 40,
                          ),
                          width: 40,
                          height: 40,
                        )
                      : SizedBox(
                          width: 40,
                          height: 40,
                          child: Image.asset(R.assetsImagesDefaultNorAvatar))),
            ],
          )
        ]);
  }

  Widget wrapItemWithMenu(item) {
    List<Function> actionsFunc = [];
    List<String> actions = [
      I18n.of(context).delete,
      I18n.of(context).reply,

    ];

    actionsFunc.add(() {
      MessageMgr().emit('Delete Select Message', widget.msg);
    });
    actionsFunc.add(() {
      print('发送引用的消息');
      MessageMgr().emit('Reply Select Message', widget.msg);
    });


    ///转发
    if (widget.msg.msgType == ChatType.TextChatType.value ||
        widget.msg.msgType == ChatType.ImageChatType.value ||
        widget.msg.msgType == ChatType.ShortVideoChatType.value ||
        widget.msg.msgType == ChatType.PlaceChatType.value ||
        widget.msg.msgType == ChatType.EmoticonType.value ||
        widget.msg.msgType == ChatType.FileChatType.value) {
      actions.add(I18n.of(context).forward);
      actionsFunc.add(() {
        print('转发消息');

        if (widget.msg.msgType == ChatType.FileChatType.value &&
            widget.msg.localFile == null) {
          showToast('请先下载文件');
          return;
        }

        AppNavigator.pushForwardPage(context, widget.msg);
      });
    }

    if (widget.msg.msgType == ChatType.FileChatType.value &&
        widget.msg.localFile != null) {
      //分享文件
      actions.add(I18n.of(context).copy_download_url);
      actionsFunc.add(() async {
        UploadUtil().copyFileUrl(widget.msg, context);
        String path = widget.msg.localFile;

        String type = 'file';
        if (path.contains('mp4') || path.contains('mp3')) {
          type = 'video';
        } else if (path.contains('png') ||
            path.contains('jpg') ||
            path.contains('jpeg') ||
            path.contains('JPG') ||
            path.contains('PNG')) {
          type = 'image';
        }

        ShareExtend.share(FileCacheMgr.replacePath(path), type);


      });

    }

    if (widget.msg.msgType == ChatType.TextChatType.value) {
      actions.insert(0, I18n.of(context).copy);
      actionsFunc.insert(0, () {
        //复制当前的文字
        print('复制文字 ${textList[curTextType]}');
        ClipboardData clipboardData =
            ClipboardData(text: textList[curTextType]);
        Clipboard.setData(clipboardData);
      });
    }

    if (widget.msg.msgType == ChatType.ShortVoiceChatType.value) {
      var soundPlayMode =
          Provider.of<KeyboardIndexProvider>(context).soundPlayMode;

      actions.add(soundPlayMode
          ? I18n.of(context).handset_playback
          : I18n.of(context).speaker_play);
      actionsFunc.add(() {
        Provider.of<KeyboardIndexProvider>(context)
            .changeSoundPlayMode(!soundPlayMode);
        SoundUtils.instance.savePlayModeConfig(soundPlayMode);
      });
    }
//    String date2 = DateTime.fromMillisecondsSinceEpoch(widget.msg.time).toString();
    bool isUrl = false;
    if (widget.msg.msgType == ChatType.TextChatType.value) {
      if (textList[curTextType].contains('http')) {
        isUrl = true;
      }
    }
    return WPopupMenu(
      child: item,
      actions: actions,
      onTap: () async {
        if (isUrl) {
          if (await canLaunch(textList[curTextType])) {
            launch(textList[curTextType]);
          }
        }
      },
      onLongPressStart: () {
        isLongPressed = true;
        setState(() {});
      },
      onLongPressEnd: () {
        isLongPressed = false;
        setState(() {});
      },
      onValueChanged: (int value) {
        print('选择的是$value个菜单');
        if (value >= 0 && value < actionsFunc.length) {
          actionsFunc[value]();
        }
      },
    );
  }

  //用户评价人工翻译,差评
  rateTranslateResult() async {
    return await HttpUtil().rateTranslateResult(widget.msg, () {
      if (mounted) {
        setState(() {});
      }
    });
  }

  _receiveJIF(MsgModel msg) {
    var text = utf8.decode(msg.msgContent);
    return extendedText(text, hideKeyboard: widget.hideKeyboard);
  }

  double _getTextWidth(String text, {double fontSize: FontSize}) {
    var tp = TextPainter(
      text: TextSpan(style: TextStyle(fontSize: fontSize), text: text),
      textAlign: TextAlign.left,
      textDirection: TextDirection.ltr,
      textScaleFactor: 1,
    );

    tp.layout(maxWidth: Screen.width - 140);

    RegExp alterStr = RegExp(r'\[([0-9]+)\]');
    Iterable<Match> matches = alterStr.allMatches(text);
//    print('~~~~~~~~~~~~~~${matches.length}~~~~~~~~~~~~~~~');

    double delta = 0;
    for (Match m in matches) {
//      print('~~~~~~~~~~~~~~${m.group(1)}~~~~~~~~~~~~~~~');
      if (int.parse(m.group(1)) > 10) {
        delta += 20 + 4 - 25;
      } else {
        delta += 20 + 4 - 16.8;
      }
    }

    return tp.width + delta;
  }

  _receiveText(MsgModel msg) {
    List<Widget> showMsg = [];
    double width = 0.0;
    if (textList.length > 0) {
      bool isUrl = false;
      if (textList[curTextType].contains('http')) {
        isUrl = true;
      }

      if (msg.refMsgContent != null && msg.refMsgContent.length > 0) {
        QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent);

        var refName = Provider.of<RefNameProvider>(context)
            .getGroupRefName(msg.sessionId, quoteMsg.sendUserId);

        var msgDate =
            DateTime.fromMillisecondsSinceEpoch(quoteMsg.sendTime.toInt());
        var showTimeStr = getTodayTime(msgDate, sendTime: quoteMsg.sendTime.toInt());

        var timetWidth = CustomUI.getRealTextWidht(showTimeStr, 13);
        var nameWidhth = CustomUI.getRealTextWidht(refName, 13);
        width = timetWidth + (nameWidhth > 70 ? 70 : nameWidhth) + 36;
        var quoteContent =
            quoteMsg.content.substring(quoteMsg.content.indexOf(':') + 2);
        var contentWidht = _getTextWidth(quoteContent, fontSize: 13);
        width = min(max(width, contentWidht), maxWidth);
        showMsg.add(InkWell(
            onTap: () {
              MessageMgr().emit('Jump to Msg', quoteMsg.sendTime.toInt());
            },
            child: Container(
              padding: EdgeInsets.all(8),
              margin: EdgeInsets.only(bottom: 5),
              decoration: BoxDecoration(
                  color: Color(0xFFC4E0F5),
                  borderRadius: BorderRadius.circular(5.5)),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Row(children: <Widget>[
                    Container(
                        constraints: BoxConstraints(maxWidth: 70),
                        child: Text(
                          refName,
                          style: TextStyle(fontSize: 13),
                          overflow: TextOverflow.ellipsis,
                        )),
                    SizedBox(width: 20),
                    Text(
                      showTimeStr,
                      style: TextStyle(fontSize: 13),
                    )
                  ]),
                  SizedBox(height: 7.5),
                  Text(
                    quoteContent,
                    style: TextStyle(fontSize: 13),
                  )
                ],
              ),
            )));
      }

      var contentWidth = _getTextWidth(textList[curTextType]);
      if (contentWidth > width && contentWidth <= maxWidth) {
        width = contentWidth;
      }

      showMsg.add(InkWell(
          onTap: () {
            if (msg.transTag == 1) {
              return;
            }
            if (msg.transTag == 2 || msg.transTag == 3) {
              setState(() {
                curTextType += 1;
                curTextType %= textList.length;
              });
              return;
            }
          },
          child: Container(
              constraints: BoxConstraints(maxWidth: maxWidth, minHeight: 22),
              alignment: Alignment.centerLeft,
              child: extendedText(
                textList[curTextType],
                color: isUrl ? Colors.blue : Constants.BlackTextColor,
                hideKeyboard: widget.hideKeyboard,
                fontSize: FontSize,
              ))));
    }

    var minWidth = width + 20;
    if (msg.transTag != 0) {
      minWidth = 200;
      showMsg.add(Padding(
          padding: EdgeInsets.symmetric(vertical: 5),
          child: Divider(color: Color(0xFFECECEC), height: 1)));
      Widget tranWidget = _transProcessWidget(msg.transTag);
      showMsg.add(tranWidget);
    }

    ///todo
    Widget text = Stack(children: <Widget>[
      Container(
        width: width + 20,
        constraints:
            BoxConstraints(maxWidth: Screen.width - 120, minWidth: minWidth),
        padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.start, children: showMsg),
        decoration: BoxDecoration(
            border: Border.all(color: ReciveBorderColor, width: 0.5),
            color: isLongPressed ? Colors.grey[300] : Colors.white,
            borderRadius: BorderRadius.all(Radius.circular(ChatRadius))),
      ),
      msg.transTag != 1 && msg.transTag != 0
          ? Positioned(
              right: 5,
              top: 5,
              child: Container(
                  child: Row(children: <Widget>[
                blueDot(curTextType == 0),
                blueDot(curTextType == 1),
                blueDot(curTextType == 2),
                //blueDot(true),
              ])))
          : Container()
    ]);

    return text;
  }

  _translateItemWidget(int code, String title, Function onTap) {
    Color color = onTap == null ? Constants.GreyTextColor : Color(0xFF087FF3);
    return InkWell(
        onTap: onTap,
        splashColor: Colors.red,
        child: Container(
            width: 80,
            child: Row(
              children: <Widget>[
                Icon(IconData(code, fontFamily: Constants.IconFontFamily),
                    color: color, size: 20),
                SizedBox(width: 5),
                Expanded(
                    child: SizedBox(
                  child: Text(
                    title,
                    style: TextStyle(color: color, fontSize: 10),
                    textScaleFactor: 1.0,
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                  ),
                ))
              ],
            )));
  }

  bool isTranslating = false;
  _transProcessWidget(int transTag) {
    double width = 160;

    Widget userTranslateWidget;
    Widget machineTranslateWidget;

    if (transTag == 1) {
      //机器翻译中
      userTranslateWidget =
          _translateItemWidget(0xe670, I18n.of(context).man_retranslate, null);

      machineTranslateWidget =
          _translateItemWidget(0xe671, I18n.of(context).robotTranslate, null);
    } else if (transTag == 2) {
      //人工翻译中
      userTranslateWidget =
          _translateItemWidget(0xe670, I18n.of(context).ManTranslate, null);
      machineTranslateWidget =
          _translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () {
        setState(() {
          curTextType += 1;
          curTextType %= textList.length;
        });
      });
    } else if (transTag == 3) {
      //机器翻译完成
      userTranslateWidget = _translateItemWidget(
          0xe670,
          I18n.of(context).man_retranslate,
          isTranslating
              ? null
              : () async {
                  isTranslating = true;

                  int money =
                      Provider.of<MoneyChangeProvider>(context, listen: false)
                          .money;

                  int voucher =
                      Provider.of<VoucherChangeProvider>(context, listen: false)
                          .voucher;

                  int needMoney = widget.msg.getNeedMoney();

                  if (needMoney > voucher + money) {
                    showToast('翻译券和H币不足');
                    return;
                  }
                  var res = await HttpUtil().getPersonalTranslate(widget.msg);
                  if (res) {
                    print('请求人工翻译成功,进行扣费');
                    setState(() {
                      widget.msg.transTag = 2;

                      //优先扣券
                      if (voucher > 0) {
                        int costQuan = min(voucher, needMoney);
                        Provider.of<VoucherChangeProvider>(context,
                                listen: false)
                            .subVoucher(costQuan);
                      }

                      //不足的话再扣H币
                      if (needMoney > voucher) {
                        Provider.of<MoneyChangeProvider>(context, listen: false)
                            .subMoney(needMoney - voucher);
                      }
                    });
                  }
                });
      machineTranslateWidget =
          _translateItemWidget(0xe671, I18n.of(context).robot_retranslate, () {
        setState(() {
          curTextType += 1;
          curTextType %= textList.length;
        });
      });
    } else if (transTag == 4 || transTag == 10) {
      //4人工翻译完成，未评论 10人工翻译完成已评论
      userTranslateWidget = InkWell(
          onTap: () {
            setState(() {
              curTextType = 0;
            });
          },
          child: Container(
              width: width / 2,
              child: Row(
                children: <Widget>[
                  InkWell(
                    child: Icon(
                        IconData(0xe641, fontFamily: Constants.IconFontFamily),
                        size: 18,
                        color:
                            transTag == 10 ? Colors.grey : Color(0xFF087FF3)),
                    onTap: transTag == 10
                        ? null
                        : () {
                            CustomUI.showIosDialog(
                                context, I18n.of(context).bad_ev, () async {
                              bool isSuccess = await rateTranslateResult();
                              if (isSuccess) {
                                Navigator.of(context).pop(true);
                                showToast(I18n.of(context).success);
                              } else {
                                showToast(I18n.of(context).fail);
                                Navigator.of(context).pop();
                              }
                            }, () {
                              Navigator.of(context).pop();
                            });
                          },
                  ),
                  SizedBox(width: 5),
                  Expanded(
                      child: SizedBox(
                    child: Text(
                      I18n.of(context).over,
                      style: TextStyle(color: Color(0xFF087FF3), fontSize: 10),
                      textScaleFactor: 1.0,
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ))
                ],
              )));
      machineTranslateWidget =
          _translateItemWidget(0xe675, I18n.of(context).see_original, () {
        setState(() {
          curTextType = textList.length - 1;
        });
      });
    }

    return Container(
      height: 26,
      alignment: Alignment.center,
      child: Row(
        children: <Widget>[
          userTranslateWidget,
          Expanded(
              child: SizedBox(child: VerticalDivider(), height: 20, width: 2)),
          machineTranslateWidget
        ],
      ),
    );
  }

  _receiveImg(BuildContext context, List<int> imgData, {String downloadData}) {
    ImageProvider provider = MemoryImage(widget.msg.localFile == null
        ? Uint8List.fromList(imgData)
        : File(widget.msg.localFile).readAsBytesSync());

    var imgSize = _getImgSize();

    return DownloadItem(
      isAutoDown: false,
      msg: widget.msg,
      onFinishTap: () {
        widget.hideKeyboard();
        showFullImg(context, widget.msg);
      },
      child: Container(
        width: imgSize.width,
        height: imgSize.height,
        child: ClipRRect(
          child: Image(
            image: provider ?? AssetImage(R.assetsImagesIcAlbum),
          ),
          borderRadius: BorderRadius.circular(5),
        ),
      ),
    );

  }

  _receiveVideo(BuildContext context, List<int> imgData,
      {String downloadData}) {
    ImageProvider provider = MemoryImage(Uint8List.fromList(imgData));
    var imgSize = _getImgSize();
    return InkWell(
        onTap: () {
          if (widget.msg.localFile != null) {
            showVideoPage(context, widget.msg.localFile);
          }
        },
        child: DownloadItem(
          isAutoDown: false,
          msg: widget.msg,
          child: Container(
            width: imgSize.width,
            height: imgSize.height,
            child: ClipRRect(
              child: Image(
                image: provider ?? AssetImage(R.assetsImagesIcAlbum),
              ),
              borderRadius: BorderRadius.circular(5),
            ),
          ),
        ));
  }

  showVideoPage(BuildContext context, String filePath) {
    widget.hideKeyboard();
    Navigator.push(context,
        MaterialPageRoute<void>(builder: (BuildContext context) {
      return VideoPage(videoPath: filePath);
    }));
  }

  Widget _receiveFileMsgItem() {
    return DownloadItem(
        isAutoDown: false,
        msg: widget.msg,
        onComplete: () {
          if (mounted) {
            setState(() {});
          }
        },
        child: Container(
            height: 100,
            constraints: BoxConstraints(maxWidth: Screen.width - 120),
            padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5),
            decoration: BoxDecoration(
                color: Colors.white,
                border: Border.all(color: ReciveBorderColor, width: 0.5),
                borderRadius: BorderRadius.all(Radius.circular(ChatRadius))),
            child: FileMsgItem(widget.msg)));
  }

  _receiveSound(BuildContext context, List<int> soundData) {
    print('收到语音消息');

    MsgModel msg = widget.msg;
    var time = widget.msg.extraInfo / 1000;
    if (time > 60) {
      time = 60.0;
    }
    bool isPlaying = false;

    if (curSoundUrl != null) {
      isPlaying = SoundUtils().isPlaying(curSoundUrl);
    }

    var soundWidget = InkWell(
      onTap: () async {
        bool isLocal = true;

        if (msg.localFile != null) {
          isLocal = true;
          curSoundUrl = msg.localFile;
        } else {
          isLocal = false;
          var sessionId = msg.sessionId;
          curSoundUrl = UploadUtil()
              .getFullUrl(msg.extraFile, sessionId, msg.channelType);
        }

        print('当前文件$curSoundUrl 本地？$isLocal');
        if (isPlaying) {
          await SoundUtils().pause();
        } else {
          print('开始播放');

          if (widget.msg.soundListened == 0) {
            widget.msg.updateSoundListened();
          } //设置为已经播放
          await SoundUtils().play(curSoundUrl, isLocal: isLocal, onPlayed: () {
            if (mounted) {
              this.setState(() {});
            }
          }, complete: () {
            if (mounted) {
              this.setState(() {});
            }
          });
        }
      },
      child: Container(
          width: 130,
          child: Row(children: <Widget>[
            Container(
              alignment: Alignment.center,
              padding: EdgeInsets.only(bottom: 2),
              margin: EdgeInsets.only(right: 10),
              width: 25.5,
              height: 25.5,
              decoration: BoxDecoration(
                  border:
                      Border.all(color: const Color(0xFF1B92C7), width: 0.5),
                  color: const Color(0xFF04A4FE),
                  shape: BoxShape.circle),
              child: Icon(
                IconData(isPlaying ? 0xe652 : 0xe653,
                    fontFamily: Constants.IconFontFamily),
                size: isPlaying ? 15 : 18,
                color: Colors.white,
              ),
            ),
            isPlaying
                ? Stack(
                    children: <Widget>[
                      Container(
                        height: 18,
                        width: 19,
                      ),
                      Positioned(
                          bottom: 0,
                          child: VideoAnim(
                            begin: 18,
                            start: 0.444,
                            end: 4.5,
                          )),
                      Positioned(
                          left: 7,
                          bottom: 0,
                          child: VideoAnim(
                            begin: 4.5,
                            end: 18,
                          )),
                      Positioned(
                          left: 14,
                          bottom: 0,
                          child: VideoAnim(
                            begin: 18,
                            end: 4.5,
                          ))
                    ],
                  )
                : Stack(
                    children: <Widget>[
                      Container(
                        height: 18,
                        width: 19,
                      ),
                      Positioned(
                          bottom: 0, child: CustomUI.buildAudioContaniner(12)),
                      Positioned(
                          left: 7,
                          bottom: 0,
                          child: CustomUI.buildAudioContaniner(4.5)),
                      Positioned(
                          left: 14,
                          bottom: 0,
                          child: CustomUI.buildAudioContaniner(18))
                    ],
                  ),
            Expanded(child: SizedBox()),
            fixedText(time.toStringAsFixed(0),
                color: Constants.BlackTextColor, fontSize: 16)
          ])),
    );

    List<Widget> showMsg = [];

    showMsg.add(DownloadItem(
      msg: widget.msg,
      child: soundWidget,
      isShowProgress: false,
    ));

    double width = 130;
    double minWidth = 0;
    if (textList.length > 0) {
      width = _getTextWidth(textList[curTextType]) + 20;
      width = min(width, Screen.width - 120);

      showMsg.add(Padding(
          padding: EdgeInsets.symmetric(vertical: 5),
          child: Divider(
            height: 1,
          )));
      showMsg.add(Container(
        child: extendedText(
          textList[curTextType],
          color: Constants.BlackTextColor,
          hideKeyboard: widget.hideKeyboard,
          fontSize: FontSize,
        ),
        alignment: Alignment.centerLeft,
        constraints:
            BoxConstraints(maxWidth: Screen.width - 120, minHeight: 22),
      ));
    }

    if (msg.transTag != 0) {
      minWidth = 200;
      showMsg.add(Divider(color: Color(0xFFECECEC), height: 3));
      Widget tranWidget = _transProcessWidget(msg.transTag);
      showMsg.add(tranWidget);
    }

    return Container(
      width: width + 20,
      constraints:
          BoxConstraints(maxWidth: Screen.width - 120, minWidth: minWidth),
      child: Column(
          crossAxisAlignment: CrossAxisAlignment.start, children: showMsg),
      padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5),
      decoration: BoxDecoration(
          color: Colors.white,
          border: Border.all(color: ReciveBorderColor, width: 0.5),
          borderRadius: BorderRadius.all(Radius.circular(ChatRadius))),
    );
  }

  void showFullImg(BuildContext context, MsgModel msg) {
    print('显示图片');
    Navigator.push(context,
        MaterialPageRoute<void>(builder: (BuildContext context) {
      return PhotoPage(msg: msg);
    }));
  }

  blueDot(bool isShow) {
    return Container(
      margin: EdgeInsets.only(right: 5),
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        color: isShow ? Color(0xFFFF7E00) : Color(0xFFCFCFCF),
      ),
      width: 6,
      height: 6,
    );
  }

  _reveiveMsg(BuildContext context) {
    Widget item;
    switch (ChatType.valueOf(widget.msg.msgType)) {
      case ChatType.TextChatType:
        item = _receiveText(widget.msg);
        break;
      case ChatType.EmoticonType:
        item = _receiveJIF(widget.msg);
        break;

      case ChatType.ImageChatType:
        if (widget.msg.extraFile != null) {
          item = _receiveImg(context, widget.msg.msgContent,
              downloadData: widget.msg.extraFile);
        } else {
          item = _receiveImg(context, widget.msg.msgContent);
        }
        break;
      case ChatType.ShortVideoChatType:
        item = _receiveVideo(context, widget.msg.msgContent,
            downloadData: widget.msg.extraFile);
        break;
      case ChatType.ShortVoiceChatType:
        item = _receiveSound(context, widget.msg.msgContent);
        break;

      case ChatType.RedWalletChatType:
        item = RedBagItem(
            Key(widget.msg.time.toString()), friendInfo.userId, widget.msg);
        break;
      case ChatType.PlaceChatType:
        item = PlaceItem(isMe: false, placeContent: widget.msg.msgContent);
        break;
      case ChatType.GiftChatType:
        item = GiftMsgItem(widget.msg.msgContent, false);
        break;
      case ChatType.FileChatType:
        item = _receiveFileMsgItem();
        break;
      default:
    }

    return wrapItemWithMenu(item);
  }

  Widget _getReceivedMessageLayout(BuildContext context) {
    bool hasHeadImg = true;

    if (friendInfo.headimgurl == null || friendInfo.headimgurl.length == 0) {
      hasHeadImg = false;
    }

    bool isShowSoundSate =
        widget.msg.msgType == ChatType.ShortVoiceChatType.value &&
            widget.msg.soundListened == 0;

    return Row(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
      Container(
          margin: const EdgeInsets.only(right: 8.0),
          child: InkWell(
            child: ClipRRect(
                borderRadius: BorderRadius.circular(8),
                child: hasHeadImg
                    ? CachedNetworkImage(
                        imageUrl: friendInfo.headimgurl,
                        placeholder: (context, url) => Image.asset(
                          Constants.DefaultHeadImgUrl,
                          width: 40,
                          height: 40,
                        ),
                        width: 40,
                        height: 40,
                      )
                    : SizedBox(
                        width: 40,
                        height: 40,
                        child: Image.asset(R.assetsImagesDefaultNorAvatar))),
            onTap: () {
              AppNavigator.pushProfileInfoPage(context, friendInfo.userId,
                  fromWhere: 0);
            },
          )),
      _reveiveMsg(context),
      isShowSoundSate
          ? Container(
              margin: EdgeInsets.only(left: 8),
              width: 40,
              height: 40,
              alignment: Alignment.centerLeft,
              child: CircleAvatar(
                radius: 3.5,
                backgroundColor: Colors.red,
              ))
          : Container()
    ]);
  }


  Widget _buildServiceCard(bool isStart, Function callBack) {
    return Container(

      alignment: Alignment.center,
      margin: EdgeInsets.all(10),
      child: Card(
        elevation: 2,
        // 阴影
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(10),
//              side: BorderSide(color: Colors.green,width: 25),
        ),
        child: Padding(
          padding: EdgeInsets.only(left: 10, right: 10, top: 15, bottom: 15),
          child: Row(
            children: <Widget>[
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(
                    isStart
                        ? I18n.of(context).translation_butler_start_service
                        : I18n.of(context).translation_butler_service_end,
                    textScaleFactor: 1.0,
                    style: TextStyle(
                        color: AppColors.NewAppbarTextColor, fontSize: 15),
                  ),
                  Text(
                    isStart
                        ? I18n.of(context).translation_butler_start_tips
                        : I18n.of(context).translation_butler_evaluation_tips,
                    textScaleFactor: 1.0,
                    style: TextStyle(
                        color: Color(0xFF797979), fontSize: 13),
                  )
                ],
              ),
              isStart
                  ? Container()
                  : Expanded(
                  child: Container(
                    margin: EdgeInsets.only(left: 15),
                    height: 30,
                    child: RaisedButton(
                        color: Color(0xff3875E9),
                        shape: RoundedRectangleBorder(
                            borderRadius:
                            BorderRadius.all(Radius.circular(10))),
                        child: Text(
                          I18n.of(context).translation_butler_evaluation,
                          textScaleFactor: 1.0,
                          style: TextStyle(color: Colors.white, fontSize: 15),
                        ),
                        onPressed: () {
                          CustomUI.buildTranslationEvaluationDialog(context);
                        }),
                  )),
            ],
          ),
        ),
      ),
    );
  }

}
