import 'dart:convert';
import 'dart:io';

import 'package:chat/chat/group_chat_item.dart';
import 'package:chat/data/UserData.dart';
import 'package:chat/data/chat_data_mgr.dart';
import 'package:chat/data/constants.dart';
import 'package:chat/data/group_data_mgr.dart';
import 'package:chat/generated/i18n.dart';
import 'package:chat/home/group_setting.dart';
import 'package:chat/models/ChatMsg.dart';
import 'package:chat/models/group_info_model.dart';
import 'package:chat/models/keyboard_provider.dart';
import 'package:chat/models/money_change.dart';
import 'package:chat/models/voucher_change.dart';
import 'package:chat/proto/all.pbserver.dart';
import 'package:chat/utils/CustomUI.dart';
import 'package:chat/utils/MessageMgr.dart';
import 'package:chat/utils/analyze_utils.dart';
import 'package:chat/utils/msgHandler.dart';
import 'package:chat/utils/net_state_widget.dart';
import 'package:chat/utils/screen.dart';
import 'package:chat/utils/sound_util.dart';
import 'package:chat/utils/sp_utils.dart';
import 'package:chat/utils/sql_util.dart';
import 'package:chat/utils/upload_util.dart';
import 'package:chat/utils/white_opacity_anim.dart';
import 'package:extended_text/extended_text.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:oktoast/oktoast.dart';
import 'package:provider/provider.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import '../r.dart';
import 'input_bar.dart';
import 'package:chat/models/ref_name_provider.dart';
import 'package:fixnum/fixnum.dart';

class GroupChatPage extends StatefulWidget {
  final GroupInfoModel groupInfoModel;
  final int enterType; // 0默认  1图片
  final dynamic enterContent;
  GroupChatPage(
      {Key key, this.groupInfoModel, this.enterType = 0, this.enterContent})
      : super(key: key);

  _GroupChatPageState createState() => _GroupChatPageState();
}

class _GroupChatPageState extends State<GroupChatPage> {
  final ItemScrollController itemScrollController = ItemScrollController();
  final ItemPositionsListener itemPositionListener =
      ItemPositionsListener.create();

  MessageMgr msgMgr = MessageMgr();

  List<MsgModel> msgList;

  KeyboardIndexProvider _keyboardIndexProvider = KeyboardIndexProvider();

  TextEditingController nickNameController = new TextEditingController();

  //统计聊天时长
  int startTime;

  //子元素的对应偏移量
  Map itemOffsetMap = {};

  //未读消息数目
  int unreadNums = 0;
  //最上一条未读消息id
  int unreadTime;

  //@消息索引
  int alterTime;

  String alterUserName = '';

  int jumpTime;

  @override
  void dispose() {
    var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;
    AnalyzeUtils.commitChatDuration(startTime, endTime);

    msgMgr.off('New Chat Message', receiveMsg);
    msgMgr.off('Keyboard Hide', dealWithKeyboardHide);
    msgMgr.off('Update Group Info', updateGroupInfo);
    msgMgr.off('Delete Select Message', _deleteItem);
    msgMgr.off('Jump to Msg', jumpToMsg);
    MsgHandler.curActiveSession = 0;
    SoundUtils().stop();

    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    print('init group chat page ${widget.groupInfoModel.sessionId}');

    getDefaultSetting();

    startTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;

    unreadNums = ChatDataMgr()
        .groupUnreadProvider
        .getUnreadCount(widget.groupInfoModel.sessionId);

    alterTime = ChatDataMgr()
        .groupUnreadProvider
        .getHavaAltertime(widget.groupInfoModel.sessionId);

    MsgHandler.updateActiveSesstion(widget.groupInfoModel.sessionId,
        isGroup: true);

    msgList = ChatDataMgr().getGroupRecord();
    if (unreadNums >= 10) {
      unreadTime = msgList[unreadNums - 1].time;
    }
    for (int i = 0; i < msgList.length; i++) {
      if (msgList[i].time == alterTime) {
        alterUserName =
            widget.groupInfoModel.getMember(msgList[i].friendId).nickName;
        break;
      }
    }

    msgMgr.on('New Chat Message', receiveMsg);
    msgMgr.on('Keyboard Hide', dealWithKeyboardHide);
    msgMgr.on('Update Group Info', updateGroupInfo);
    msgMgr.on('Delete Select Message', _deleteItem);
    msgMgr.on('Jump to Msg', jumpToMsg);

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (widget.enterType == 1) {
        print('接收到的:${widget.enterContent}');
        _sendFile(File(widget.enterContent));
      } else if (widget.enterType == 2) {
        //转发消息
        MsgModel originMsg = widget.enterContent;
        MsgModel msg = MsgHandler.createSendMsg(
            ChatType.valueOf(originMsg.msgType), originMsg.msgContent,
            channelType: ChatChannelType.Group);
        msg.extraInfo = originMsg.extraInfo;

//        msg.extraFile = originMsg.extraFile;
        if (originMsg.extraFile == null ||
            originMsg.extraFile.contains('http')) {
          msg.extraFile = originMsg.extraFile;
        } else {
          msg.extraFile = UploadUtil().getFullUrl(
              originMsg.extraFile, originMsg.sessionId, originMsg.channelType);
        }
        msg.localFile = originMsg.localFile;
        if (msg.localFile != null) {
          msg.state = MsgState.Uploaded;
        }

        sendMsg(msg);
      }
    });
  }

  jumpToMsg(time) {
    //var screenItemNums = itemPositionListener.itemPositions.value.length;
    jumpTime = time;
    int jumIndex = 0;
    for (int i = 0; i < msgList.length; i++) {
      if (time == msgList[i].time) {
        jumIndex = i - 1; // - screenItemNums + 2;
        break;
      }
    }
    if (jumIndex < 0) {
      jumIndex = 0;
    }
    if (jumIndex > msgList.length - 1) {
      jumIndex = msgList.length - 1;
    }
    itemScrollController.scrollTo(
        index: jumIndex, duration: new Duration(microseconds: 1));
  }

  void _sendFile(File file) async {
//    File file = await FilePicker.getFile();
    int fileSize = file.lengthSync();
    print('选择的文件 ${file.path} 大小 $fileSize');

    if (fileSize > 33 * 1024 * 1024) {
      showToast('文件大于33M');
      return;
    }

    var fileName = file.path.split('/').last;
    print('fileName  $fileName');

    var ext = '';
    var extList = fileName.split('.');
    if (extList.length > 1) {
      ext = extList.last;
    }
    print('ext  $ext');

    var fileMsg = FileChat.create();
    fileMsg.type = ext;
    fileMsg.size = fileSize;
    fileMsg.name = fileName;

    var msg = MsgHandler.createSendMsg(
        ChatType.FileChatType, fileMsg.writeToBuffer(),
        friendId: 0, localFile: file.path, channelType: ChatChannelType.Group);

    sendMsg(msg);
  }

  updateGroupInfo(args) {
    print('更新群信息');
    if (mounted) {
      setState(() {});
    }
  }

  void getDefaultSetting() async {
    bool soundPlayMode =
        (await SPUtils.getBool(Constants.SOUND_PLAY_MODE)) ?? false;

    _keyboardIndexProvider.init(soundPlayMode);
  }

  dealWithKeyboardHide(args) {
    if (_keyboardIndexProvider.curKeyboardIndex == 0) {
      readOnly();
    }
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> actions = [];
    actions.add(Row(
      children: <Widget>[
        CustomUI.buildImageLabel("assets/images/voucher.png",
            Provider.of<VoucherChangeProvider>(context).voucher,
            imgOpc: 0.5, imgHeight: 13),
        CustomUI.buildImageLabel(
            R.assetsImagesCoin, Provider.of<MoneyChangeProvider>(context).money,
            isLeft: false)
      ],
    ));
    actions.add(widget.groupInfoModel.isInGroup
        ? IconButton(
            icon: Icon(Icons.more_horiz),
            iconSize: 22,
            onPressed: () {
              //进入群管理界面
              hideKeyBoard();

              Navigator.of(context).push(
                new MaterialPageRoute(
                  builder: (context) {
                    return GroupSetting(
                      groupInfoModel: widget.groupInfoModel,
                    );
                  },
                ),
              );
            },
          )
        : IconButton(
            icon: Icon(Icons.delete),
            iconSize: 22,
            color: Colors.redAccent,
            onPressed: () {
              //进入群管理界面
              quiteGroup();
            },
          ));

    Map refMap = Provider.of<RefNameProvider>(context).refMap;

    bool isHaveUnreadNews = unreadTime != null;
    bool isAlterYou = alterTime != null;

    return MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (_) => _keyboardIndexProvider),
          Provider<bool>.value(value: true),
          Provider<GroupInfoModel>.value(value: widget.groupInfoModel),
        ],
        child: GestureDetector(
            onTap: hideKeyBoard,
            child: ExtendedTextSelectionPointerHandler(
              ///选择文字，消除弹窗
              builder: (states) {
                return Listener(
                  child: Scaffold(
                      resizeToAvoidBottomInset: false,
                      backgroundColor: const Color(0xFFE2E9F1),
                      appBar: AppBar(
                          backgroundColor: AppColors.NewAppbarBgColor,
                          title: Text(
                            widget.groupInfoModel.getGroupName(refMap),
                            textScaleFactor: 1.0,
                            style: TextStyle(
                                color: Constants.BlackTextColor,
                                fontSize: 16.47),
                          ),
                          leading: CustomUI.buildCustomLeading(context),
                          titleSpacing: -10,
                          elevation: 1,
                          centerTitle: false,
                          actions: actions),
                      body: SafeArea(
                          child: Stack(
                        children: <Widget>[
                          Column(
                            children: <Widget>[
                              NetStateWidget(),
                              Expanded(child: _buildMessageList()),
                              InputBar(sendMsg: sendMsg),
                            ],
                          ),
                          isHaveUnreadNews
                              ? Positioned(
                                  top: 32.5,
                                  right: 0,
                                  child: InkWell(
                                      onTap: () {
                                        jumpToMsg(isAlterYou
                                            ? alterTime
                                            : unreadTime);
                                        unreadTime = null;
                                        setState(() {});
                                      },
                                      child: Container(
                                        alignment: Alignment.center,
                                        decoration: BoxDecoration(
                                          boxShadow: [
                                            BoxShadow(
                                              color: Color(0x33000000), //阴影颜色
                                              blurRadius: 10.0, //阴影大小
                                            )
                                          ],
                                          borderRadius: BorderRadius.only(
                                              topLeft: Radius.circular(80),
                                              bottomLeft: Radius.circular(80)),
                                          color: Colors.white,
                                        ),
                                        constraints:
                                            BoxConstraints(minWidth: 120),
                                        height: 39,
                                        child: Row(
                                          children: <Widget>[
                                            Icon(
                                              Icons.arrow_upward,
                                              color: Color(0xFF3875E9),
                                              size: 20,
                                            ),
                                            Text(
                                              isAlterYou
                                                  ? '$alterUserName @你'
                                                  : '$unreadNums条新消息',
                                              style: TextStyle(
                                                  color: Color(0xFF3875E9)),
                                            )
                                          ],
                                        ),
                                      )))
                              : Container()
                        ],
                      ))),
                  onPointerDown: (value) {
                    for (var state in states) {
                      if (!state.containsPosition(value.position)) {
                        //clear other selection
                        state.clearSelection();
                      }
                    }
                  },
                  onPointerMove: (value) {
                    //clear other selection
                    for (var state in states) {
                      if (!state.containsPosition(value.position)) {
                        //clear other selection
                        state.clearSelection();
                      }
                    }
                  },
                );
              },
            )));
  }

  //更新各个子元素的偏移位置
  _updateMsgItemOffset() {
    if (msgList.length == 0) {
      return;
    }

    var myId = UserData().basicInfo.userId;
    double offset = 0;
    for (var i = 0; i < msgList.length; i++) {
      MsgModel msg = msgList[i];

      double itemHeight = 70;
      switch (ChatType.valueOf(msg.msgType)) {
        case ChatType.TextChatType:
          //if (msg.from == myId) {
          var text = utf8.decode(msg.msgContent);
          itemHeight = 21 + _getTextHeight(text);
          //} else {}
          break;
        case ChatType.ShortVoiceChatType:
          if (msg.from == myId) {
            itemHeight = 22.5 + 24;
          } else {}
          break;
        case ChatType.ImageChatType:
          itemHeight = _getImgHeight(msg);
          break;
        case ChatType.ShortVideoChatType:
          itemHeight = _getImgHeight(msg);
          break;
        case ChatType.EmoticonType:
          itemHeight = 40;
          break;
        case ChatType.RedWalletChatType:
          print('红包消息');
          itemHeight = 70;
          break;
        case ChatType.PlaceChatType:
          itemHeight = 100 + 40.0;
          break;
        case ChatType.GroupChatNoticeType:
          itemHeight = 40;
          break;
        case ChatType.GiftChatType:
          itemHeight = 40;
          break;
        case ChatType.FileChatType:
          itemHeight = 80;
          break;
        default:
      }

      itemOffsetMap[i] = offset;
      offset += itemHeight;
    }
  }

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

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

    return tp.height;
  }

  double _getImgHeight(MsgModel msg) {
    double aspectRatio = msg.extraInfo / 100;

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

    double height;
    if (maxWidth / maxHeight > aspectRatio) {
      height = maxHeight;
    } else {
      height = maxWidth / aspectRatio;
    }

    return height;
  }

  Widget _buildMessageList() {
    return Container(
      alignment: Alignment.topCenter,
      child: msgList.length == 0
          ? Padding(
              padding: EdgeInsets.all(10),
              child: Text(
                I18n.of(context).chat_tips,
                textAlign: TextAlign.center,
                textScaleFactor: 1.0,
                style: TextStyle(color: Colors.grey),
              ))
          : Scrollbar(
              child: ScrollablePositionedList.builder(
              physics: new ClampingScrollPhysics(),
              itemCount: msgList.length,
              itemBuilder: _buildItem,
              itemScrollController: itemScrollController,
              itemPositionsListener: itemPositionListener,
              padding: EdgeInsets.all(8.0),
              reverse: true,
              hitCallback: hideKeyBoard,
            )),
    );
  }

  hideKeyBoard() {
    _keyboardIndexProvider.changeSelectIndex(-1);
  }

  readOnly() {
    _keyboardIndexProvider.changeReadOnlyKey(true);
  }

  sendMsg(MsgModel msg) {
    if (!widget.groupInfoModel.isInGroup) {
      //如果不在该群
      showToast(I18n.of(context).not_in_group);
      return;
    }

    MsgHandler.insertMsgToDB(msg);
    MsgHandler.sendChatMsg(msg);
    if (mounted) {
      setState(() {
        itemScrollController.jumpTo(index: 0);
      });
    }
  }

  MsgModel msg;
  int count = 0;
  testBig(MsgModel msg) async {
    for (int k = 0; k < 100; k++) {
      msg.msgContent = utf8.encode('测试$count');
      Int64 time = Int64((DateTime.now()).millisecondsSinceEpoch);
      msg.time = time.toInt();
      MsgHandler.insertMsgToDB(msg);
      MsgHandler.sendChatMsg(msg);
      await Future.delayed(Duration(milliseconds: 300), () {});
      count++;
    }
    count = 0;
    print('攻击完毕');
    showToast('攻击完毕');
  }

  void receiveMsg(args) {
    print("msgList.length: ${msgList.length}");
    if (args != widget.groupInfoModel.sessionId) {
      return;
    }
    if (mounted) {
      setState(() {});
    }
  }

  _deleteItem(msg) {
    MessageMgr().emit('Cancel Request', msg);
    print('#### 开始删除--');
    msgList.remove(msg);
    setState(() {});
    SqlUtil().deleteSigleRecordWith(msg.sessionId, msg.time);
  }

  Widget _buildItem(BuildContext context, int index) {
    var lastMsgTime;

    if (index < msgList.length - 1) {
      lastMsgTime = msgList[index].time;
    }

    MsgModel msg = msgList[index];
    var result;

    if (msg.from == 0) {
      result = GroupChatPageItem(
          key: Key(msg.time.toString()), msg: msg, lastMsgTime: lastMsgTime);
    } else {
      result = GroupChatPageItem(
          key: Key(msg.time.toString()),
          msg: msg,
          memberModel: widget.groupInfoModel.getMember(msg.from),
          hideKeyboard: readOnly,
          lastMsgTime: lastMsgTime);
    }
    if (msg.time == jumpTime) {
      result = WhiteOpacityAnim(
        key: Key(msg.time.toString()),
        child: result,
        animFinishCallback: () {
          jumpTime = null;
        },
      );
    }
    return result;
  }

  quiteGroup() {
    var function = () {
      GroupInfoMgr().deleteGroup(widget.groupInfoModel.sessionId);
      MessageMgr().emit('Quit Group', widget.groupInfoModel.sessionId);
      Navigator.of(context).popUntil(ModalRoute.withName('/main'));
      MsgHandler.quitGroup(widget.groupInfoModel.sessionId);
    };

    showModalBottomSheet(
      context: context,
      backgroundColor: Colors.transparent,
      builder: (BuildContext context) {
        return Container(
          decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(13), topRight: Radius.circular(13))),
          height: 225,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Padding(
                padding: EdgeInsets.fromLTRB(15, 15, 15, 13),
                child: Text(
                  I18n.of(context).quit_group_tips,
                  textScaleFactor: 1.0,
                  style: TextStyle(fontSize: 12, color: Color(0xff777777)),
                ),
              ),
              Divider(
                color: Color(0xffE5E5E5),
              ),
              InkWell(
                onTap: function,
                child: Container(
                  height: 60,
                  alignment: Alignment.center,
                  child: Text(I18n.of(context).determine,
                      textScaleFactor: 1.0,
                      style: TextStyle(
                          fontSize: 18, color: Constants.ConfrimButtonColor)),
                ),
              ),
              Container(
                color: Color(0xffF2F2F2),
                height: 4,
              ),
              InkWell(
                onTap: () {
                  Navigator.of(context).pop();
                },
                child: Container(
                  height: 60,
                  alignment: Alignment.center,
                  child: Text(I18n.of(context).cancel,
                      textScaleFactor: 1.0,
                      style: TextStyle(fontSize: 18, color: Color(0xff4B4B4B))),
                ),
              )
            ],
          ),
        );
      },
    );
  }
}
