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

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:multi_image_picker/multi_image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sport/bean/message.dart';
import 'package:sport/db/message_db.dart';
import 'package:sport/pages/social/chat_page.dart';
import 'package:sport/services/api/inject_api.dart';
import 'package:sport/utils/toast.dart';
import 'package:sport/widgets/button_primary.dart';
import 'package:sport/widgets/decoration.dart';
import 'package:sport/widgets/space.dart';

import '../application.dart';
import 'dialog/request_dialog.dart';

class MenuBar extends StatefulWidget {
  final String inputField;
  final Function closeMenuCallBack;
  final Widget messageList;
  final Function scrollToBottom;
  final MenuIdentity menuIdentity;
  final Function sendCallBack;
  final GlobalKey globalkey;

  MenuBar(
    this.messageList, {
    @required this.menuIdentity,
    this.inputField,
    this.closeMenuCallBack,
    this.scrollToBottom,
    this.sendCallBack,
    this.globalkey,
  });

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _MenuBarState();
  }
}

class _MenuBarState extends State<MenuBar> with WidgetsBindingObserver, InjectApi {
  GlobalKey _myKey = new GlobalKey(); // 用来定位Message位置

  List<Asset> imageList = []; // 选图片的列表
  File _image; // 拍照后的图片路径

  String _textFieldValue = ""; // TextField的文本

  // TextField的 controller
  TextEditingController _controller;

  FocusNode _focusNode = new FocusNode(); // TextField 的 focus

  ValueNotifier<bool> _postable = ValueNotifier(false);

  double keyBoardHeight = 270.0; // 初始化下面menu的高度 后续会动态调整后 优化

  bool isFirst = true; // flag 优化menu高度的操作

  String emojiJson; // 读取的JSON

  int isShowMenuBottomIndex = 0; // 用数字去优化if else 的判断

  double height;

  Timer _timer;

  bool showInput = true;

  @override
  void didUpdateWidget(MenuBar oldWidget) {
    super.didUpdateWidget(oldWidget);
    widget.scrollToBottom();
  }

  void initState() {
    super.initState();

    initEmoji();

    _controller = TextEditingController()
      ..addListener(() {
        _postable.value = _controller.value.text.isNotEmpty;
      });
//    _focusNode.addListener(() {
//      if (_focusNode.hasFocus) {
////        setState(() {
////          isShowExtMenu = false;
////        });
//      }
//    });
  }

  // 直接进来就请求了 不要 搞这些骚的....
  void initEmoji() async {
    String json = await DefaultAssetBundle.of(context).loadString("lib/assets/json/emoji_list.json");
    setState(() {
      emojiJson = json;
    });
  }

  //页面销毁
  @override
  void dispose() {
    super.dispose();
    //释放
    _focusNode?.dispose();
    _timer?.cancel();
    _postable?.dispose();
    _controller?.dispose();
  }

  // 这里 插库 + 渲染更新...
  Future add(MessageInstance message) async {
    // 聊天的时候 是没有返回 curId的 本地存储的时候 就得自己构造一个? 或者是不存?
    await MessageDB().insert(new MessageItem(message: message, status: 0, userId: message.toUser.id, curId: 0));

    var list = await MessageDB().findHasUserId(message.toUser.id);

    if (list.length == 0) {
      await MessageDB().insertUser(new UserTableInfo(userId: message.toUser.id, isTop: 0));
    }

    // view 上setstate 渲染的...
    widget.sendCallBack(message); // 添加完 在 callBack...
  }

  _postFeedBackpostFeedBack(String content, {int typeId = 0}) async {
    typeId == null ? typeId = 0 : typeId = typeId;
    await api.postFeedback(typeId, content, extra: await Application.getDeviceInfo());
  }

  Widget extMenuItem(
    String text,
    String url,
    int index,
  ) {
    String error;
    void getPicture() async {
      try {
        // 这里是拿到想要发的图片
        List<Asset> resultList = await MultiImagePicker.pickImages(
            maxImages: 9,
            selectedAssets: imageList,
            materialOptions: MaterialOptions(
              actionBarTitle: "选择图片",
              allViewTitle: "选择图片",
              useDetailsView: true,
              startInAllView: true,
              selectionLimitReachedText: "不能选择更多了~",
            ),
            cupertinoOptions: CupertinoOptions(
              selectionFillColor: "#ff11ab",
              selectionTextColor: "#ffffff",
              selectionCharacter: "✓",
            ));
        List<String> urls = [];
        if (resultList != null) {
          Directory tempDir = await getTemporaryDirectory();
          Directory directory = new Directory('${tempDir.path}/upload');
          if (!directory.existsSync()) {
            directory.createSync();
            print('文档初始化成功，文件保存路径为 ${directory.path}');
          }

          for (var i = 0; i < resultList.length; i++) {
            Asset asset = resultList[i];
            ByteData byteData = await asset.getByteData(quality: 85);
            File file = File('${directory.path}/${DateTime.now().millisecondsSinceEpoch}_$i.jpg');
            List<int> bytes = byteData.buffer.asUint8List().toList();
            print('临时文件 ${file.path} ${bytes.length}');
            file.writeAsBytesSync(bytes);
            String url = (await api.postChatUpload(file)).data["url"];
            urls.add(url);
            file.delete();
          }
        }

        if (widget.menuIdentity.menuScene == "chat") {
          if (urls.length > 0) {
            for (int i = 0; i < urls.length; i++) {
              MessageInstance message = (await api.postChatSend(widget.menuIdentity.userId, "image", '{"url":"${urls[i]}"}')).data;
              add(message);
            }
          }
        }
      } on Exception catch (e) {
        error = e.toString();
      }
    }

    void getPhoto() async {
      try {
        // 拍完直接发...
        final pickedFile = await new ImagePicker().getImage(source: ImageSource.camera, imageQuality: 70);

        // 如果是聊天 直接发 ...
        if (widget.menuIdentity.menuScene == "chat") {
          await request(context, () async {
            // 先上传
            var data = (await api.postChatUpload(File(pickedFile.path))).data;
            print(data['url']);
//          print("${data}-----------------------------");
            MessageInstance message = (await api.postChatSend(widget.menuIdentity.userId, "image", '{ "url":"${data['url']}" }')).data;
            add(message);
          });
        }
      } on Exception catch (e) {
        error = e.toString();
      }
    }

    List<Function> menuOperation = [getPicture, getPhoto];

    return InkWell(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Container(
            padding: EdgeInsets.fromLTRB(14.0, 16.0, 14.0, 14.0),
            child: Image.asset("lib/assets/img/$url.png"),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10.0),
              color: Color(0xfff1f1f1),
            ),
          ),
          SizedBox(
            height: 5.0,
          ),
          Text("$text")
        ],
      ),
      onTap: () {
        menuOperation[index]();
      },
    );
  }

  Widget _emoJiList() {
    if (emojiJson != null && emojiJson.length != 0) {
      List<dynamic> data = json.decode(emojiJson);
      return Container(
        height: keyBoardHeight,
        padding: EdgeInsets.only(left: 5, top: 5, right: 5, bottom: 5),
        decoration: BoxDecoration(color: Colors.white, border: Border(top: BorderSide(width: 1.0, color: Color(0xFFDCDCDC)))),
        child: GridView.custom(
          padding: EdgeInsets.all(3),
          shrinkWrap: true,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 6,
            mainAxisSpacing: 0.5,
            crossAxisSpacing: 6.0,
          ),
          childrenDelegate: SliverChildBuilderDelegate(
            (context, index) {
              return GestureDetector(
                onTap: () {
                  String intPutString = _controller.text + String.fromCharCode(data[index]["unicode"]);

                  var content = intPutString;
                  _controller.value = TextEditingValue(
                      // 设置内容
                      text: content,
                      // 保持光标在最后
                      selection: TextSelection.fromPosition(TextPosition(affinity: TextAffinity.downstream, offset: content.length)));
                  // 主要是 onchange 没有办法 加上 表情 ...
                  setState(() {});
                },
                child: Center(
                  child: Text(
                    String.fromCharCode(data[index]["unicode"]),
                    style: TextStyle(fontSize: 33),
                  ),
                ),
              );
            },
            childCount: data.length,
          ),
        ),
      );
    }
    return Container();
  }

  Widget menuBottom() {
    // 这里的软键盘动画还是有点问题....
    List<Widget> list = [
      Container(),
      SizedBox(
        height: MediaQuery.of(context).viewInsets.bottom,
      ),
      Container(
          height: keyBoardHeight,
          padding: EdgeInsets.only(left: 24.0, right: 24.0),
          decoration: BoxDecoration(color: Colors.white, border: Border(top: BorderSide(width: 1.0, color: Color(0xFFDCDCDC)))),
          child: GridView(
              shrinkWrap: true,
              padding: EdgeInsets.only(top: 24.0),
              physics: NeverScrollableScrollPhysics(),
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 4, //横轴三个子widget
              ),
              children: <Widget>[
                extMenuItem("图片", "bbs_icon_picture", 0),
                extMenuItem("拍照", "bbs_icon_photo", 1),
              ])),
      _emoJiList(),
    ];
    return list[isShowMenuBottomIndex];
  }

  Widget build(BuildContext context) {
    // 优化 输入键盘高度 跟 菜单栏高度的操作
    if (isFirst && MediaQuery.of(context).viewInsets.bottom != 0.0) {
      setState(() {
        keyBoardHeight = MediaQuery.of(context).viewInsets.bottom;
        isFirst = false;
      });
    }

    return Column(
      children: <Widget>[
        Expanded(
          child: Column(
            children: <Widget>[
              Flexible(
                  child: GestureDetector(
                onTap: () {
                  setState(() {
                    isShowMenuBottomIndex = 0;
                  });
                  _focusNode.unfocus();
                },
                child: widget.messageList,
              )),
            ],
          ),
        ),
        if (showInput)
//          Column(
//            children: <Widget>[
////              Container(
////                color: Colors.white,
////                padding: EdgeInsets.only(top: 10.0,left: 10.0,right: 10.0,bottom: 10.0),
////                child:
////              ),
//              ,
//            ],
//          ),
          Container(
              padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
              decoration: shadowTop(),
              child: Row(
                children: <Widget>[
                  GestureDetector(
                    onTap: () async {
                      if (_focusNode.hasFocus) {
                        await SystemChannels.textInput.invokeMethod('TextInput.hide');
                        setState(() {
                          isShowMenuBottomIndex = 2;
                        });
                      } else {
                        setState(() {
                          isShowMenuBottomIndex = 2;
                        });
                      }
                    },
                    child: Padding(
//                padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
                      child: Image.asset("lib/assets/img/bbs_icon_addmore.png"),
                      padding: EdgeInsets.only(right: 12.0),
                    ),
                  ),
                  GestureDetector(
                    onTap: () {
                      setState(() {
                        isShowMenuBottomIndex = 3;
                        FocusScope.of(context).requestFocus(_focusNode);
                        if (_focusNode.hasFocus) {
                          SystemChannels.textInput.invokeMethod('TextInput.hide');
                        }
                      });
                    },
                    child: Padding(
//                padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
                      child: Image.asset("lib/assets/img/bbs_icon_expression.png"),
                      padding: EdgeInsets.only(right: 12.0),
                    ),
                  ),
                  Expanded(
                    child: CupertinoTextField(
                      controller: _controller,
                      focusNode: _focusNode,
                      keyboardType: TextInputType.multiline,
                      style: TextStyle(
                        fontSize: 16.0,
                      ),
                      strutStyle: StrutStyle(forceStrutHeight: true, height: 1.4),
                      minLines: 1,
                      maxLines: 3,
//                              maxLength: 200,
                      onChanged: (value) {
//                         setState(() {
// //                                  _textFieldValue = value;
//                         });
                      },
                      onTap: () {
                        setState(() {
                          isShowMenuBottomIndex = 1;
                        });
                        widget.scrollToBottom();
                      },
                      decoration: BoxDecoration(shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(10)), color: Color(0xfff1f1f1)),
                    ),
                  ),
                  Space(
                    width: 5.0,
                  ),
                  ValueListenableBuilder(
                      valueListenable: _postable,
                      builder: (_, able, __) => PrimaryButton(
                            width: 75,
                            height: 35.0,
                            content: "发送",
                            callback: () async {
                              if (_controller.text.length <= 0) {
                                ToastUtil.show("请输入正确的内容");
                                return;
                              }

                              if (widget.menuIdentity.menuScene == "chat") {
                                MessageInstance message = (await api.postChatSend(widget.menuIdentity.userId, "text", '{"text":"${_controller.text}"}')).data;
                                if(message != null)
                                  await add(message); // await 是等待的标志 我等待完 在做后面的init 的事?
                                _controller.text = "";
                              }
                              if (widget.menuIdentity.menuScene == "feedback") {
                                await _postFeedBackpostFeedBack(_textFieldValue);
                              }

                              // 这里可能传不了 callback 所有需要的值都在menu bar里面 只能通过传 不同的 场景 进行 不同的操作
                            },
                            shadow: able == true,
//                            buttonColor: able == false  ? Color(0xffd2d2d2) : null,
                              buttonColor: able == false ? Color(0xffFFC400).withOpacity(0.3) : null,
                      )),
                ],
              )),
        // 底部的骚操作
        menuBottom(),
      ],
    );
  }
}

// 只是用来封装 scrollToBottom
class GetMenuController {
  ScrollController scrollMenuController = new ScrollController();

  // 暂时不用 这个 scrollToBottom ...
  void scrollToBottom(BuildContext context, GlobalKey key, bool first) {
    scrollMenuController.addListener(() {
      print("[offSet:]${scrollMenuController.offset}----------------------");
    });

    // 页面一屏的高度
    double pageHeight = MediaQuery.of(context).size.height;

    // 头部的高度...
    double appBarAndHeight = MediaQuery.of(context).padding.top + 56;

    // 尾部的高度...
    double bottomHeight = 160;

    // scrollView 的 高度 ...
    double scrollHeight = key.currentContext.size.height;

    print("[scrollHeight]:$scrollHeight----------------------------");

    double position = scrollMenuController?.position?.maxScrollExtent;

    double currentOffset = scrollMenuController.offset;

    double getScrollTop(bool first) {
      if (first) {
        return scrollHeight;
      } else {
        // 不需要滚动的状态... 当前 所处的位置 需不需要 加上 bottomHeight...
        if (currentOffset < bottomHeight) {
          return position + appBarAndHeight + bottomHeight;
        } else {
          return position + appBarAndHeight;
        }
      }
    }

    if (scrollMenuController.hasClients) {
      Future.delayed(Duration(milliseconds: 30), () {
        scrollMenuController?.jumpTo(getScrollTop(first));
      });
    }
  }

  // 后续修改为用这个...
  void scroll() {
//    SchedulerBinding.instance.addPostFrameCallback((_) {
////here the sublist is already build
//      scrollMenuController
//          .jumpTo(scrollMenuController.position.maxScrollExtent);
//      print(
//          "${scrollMenuController.position.minScrollExtent} - ${scrollMenuController.position.maxScrollExtent}");
//    });
  }
}

// 自己内部传的 bean 用来鉴别 是什么 场景使用的 menuBar
class MenuIdentity {
  String menuScene; // 当前的MenuBar 所属的场景在哪 比如 聊天 chat / 社区 social / 反馈 feedBack 等
  int userId; // Chat的时候需要的userId

  MenuIdentity({this.menuScene, this.userId});

  MenuIdentity.fromJson(Map<String, dynamic> json) {
    menuScene = json['menuScene'];
    userId = json['userId'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['menuScene'] = this.menuScene;
    data['userId'] = this.userId;
    return data;
  }
}
