class WebSocketServerRequestHandler(socketserver.BaseRequestHandler):
    def __init__(self, request, client_address, server):
        self.keep_alive = True
        self.handshake_done = False

        self.is_master = False  # 是否是控制机
        self.is_client = True  # 是否是用户机

        self.xid = None  # 绑定的编号
        self.pwd = None  # 绑定的密码

        self.master_xid = None  # 控制机的编号
        self.master_pwd = None  # 控制机的密码

        self.json_type = True  # 默认以JSON类型传输数据,False: 接收到的数据不能解析为json数据了。

        self.last_send_message = None  # 上次发送的数据

        self.selector = selectors.DefaultSelector()
        self.selector.register(request, selectors.EVENT_READ)
        self.server = server  # type: WebSocketServer
        self.message = Message()

        self.queue = queue.Queue()  # 默认队列

        self.request = request
        self.master_request = None  # type: socket.socket
        self.master_handler = None  # type: WebSocketServerRequestHandler
        self.client_requests = []  # 所有用户机的socket

        super().__init__(request, client_address, server)

    def reg_send(self):
        # print("reg_send.....{}".format(self.request.getpeername()))
        self.selector.modify(self.request, selectors.EVENT_WRITE)

    def reg_read(self):
        # print("reg_read.....{}".format(self.request.getpeername()))
        self.selector.modify(self.request, selectors.EVENT_READ)

    def handle(self):

        # print("handle.....{}".format(self.request.getpeername()))

        while self.keep_alive:
            # 获取图像数据
            # print("selector.select>>>>>>{}".format(self.request.getpeername()))

            selection_keys = self.selector.select()

            for key, events in selection_keys:
                if key.fileobj == self.request:
                    if events == selectors.EVENT_READ:
                        # 客户端读事件
                        # print("read_message。。。。")
                        self.read_message()
                    elif events == selectors.EVENT_WRITE:
                        # 客户端写事件
                        # print("send_message。。。。")
                        self.send_message()

    def handshake(self, request_header):
        # 从请求的数据中获取 Sec-WebSocket-Key, Upgrade
        sock = self.request  # type: socket.socket

        request, payload = request_header.split("\r\n", 1)

        maps = Properties(separator=':',
                          ignore_case=True).load(payload)  # type: dict

        # try:
        self.handshake_done = handshake(self.request, maps)

        if self.handshake_done > 0:
            self.server.new_client(self)

            ip = get_real_ip(maps)
            if not ip or ip == "unknown":
                ip = sock.getpeername()[0]

            print('handshake success...', ip)

        else:
            self.keep_alive = False

        # except ValueError as ve:
        #     print("handshake.ve", ve)

    def read_message(self):
        """
        读取客户端的信息
        :return:
        """
        try:
            # 客户端
            message = self.request.recv(socket_buffer_size)

            if not message:
                print('read_message: client disconnect. received empty data!')
                self.keep_alive = False
                return

            if self.handshake_done is False:
                try:
                    request_header = str(message, encoding='ascii')
                except UnicodeDecodeError as e:
                    print("read_message.UnicodeDecodeError:", e)
                    self.keep_alive = False
                    return
                self.handshake(request_header)
            else:

                # 如果是用户机的话,就通过解包的来获取相关的操作信息
                self.message.reset_pos()
                # 解析文本
                # 在读下一个字符,看看有没有客户端两次传入,一次解析的。
                # 考虑两份数据一次接收的问题。需要先看一下第一个字符是否有效。
                while self.message.read_bytes(message, 1):
                    self.message.backward_pos()
                    try:
                        # 1,控制机只负责上传图片数据,接收JSON数据
                        # 2,用户机只负责上传JSON数据,接收图片数据
                        # 当没有确定是什么类型的机器,默认都是通过JSON类型上传/接收数据。
                        opcode, decoded = self.message.unpack_message(message)

                        if opcode == 0x01:
                            # 文本
                            user_data = json.loads(
                                str(decoded, encoding="utf-8"))  # type: dict
                            self.handle_client_message(user_data)
                        elif opcode == 0x02:
                            # 二进制
                            if self.is_master:
                                # 控制机器
                                # 接收到了图像数据,将图像发送给用户机
                                # 发送数据给用户机
                                if len(self.client_requests) > 0:
                                    # encode_message = pack_message(decoded, OPCODE_BINARY)
                                    # print("encode_message:", encode_message)
                                    self.client_send_message(
                                        pack_message(decoded, OPCODE_BINARY))
                                    # 响应数据给控制机,告诉控制机,我已经将数据发送给对方了。
                                    reply_message = {
                                        "size": {
                                            "width": 0,
                                            "height": 0
                                        },
                                        "action": "capture",
                                        "emit": "change"
                                    }
                                else:
                                    reply_message = {
                                        "size": {
                                            "width": 0,
                                            "height": 0
                                        },
                                        "action": "pause"
                                    }

                                self.queue.put(
                                    json.dumps(reply_message).encode(),
                                    block=False)
                                self.reg_send()

                    except ValueError as e:
                        print(e)
                        self.keep_alive = False

                    # print('read next....')
        except (ConnectionAbortedError, ConnectionResetError,
                TimeoutError) as es:
            # [Errno 54] Connec tion reset by peer
            # self.shutdown_request()
            print(es)
            self.finish()

    def handle_client_message(self, user_data: dict):
        """
        处理用户机的消息
        :param user_data: 用户机提交过来的信息
        :return:
        """
        print("收到用户信息:", user_data)
        if "xid" in user_data:
            # 客户端上传xid信息
            self.xid = user_data.get("xid", None)
            self.server.new_client(self)
        if "pwd" in user_data:
            # 客户端上传密码
            self.pwd = user_data.get("pwd", None)

        if "master" in user_data:
            master = user_data.get("master", None)  # type: dict
            if master:
                self.master_xid = master.get("xid", None)
                self.master_pwd = master.get("pwd", None)
                # 可以进行校验密码
                # 密码校验成功
                # 可以开始连通目标机器

                handler = self.server.get_client(
                    self.master_xid)  # type: WebSocketServerRequestHandler
                if handler and handler.request:
                    print("找到目标机器..")

                    handler.is_master = True  # 设置为控制机
                    handler.is_client = False  # 当前机器不能作为客户端,意思是不能连接到其他机器
                    handler.json_type = False  # 接收到的数据不能解析为json数据了。

                    self.master_request = handler.request  # type: socket.socket
                    self.master_handler = handler

                    # 如果关闭的socket没有在client_requests中移除的话,那么就会一直在收。
                    print("handler.client_requests: ", handler.client_requests)
                    if len(handler.client_requests) > 0:
                        # 已经有请求存在,说明已经有在交互了,无需再次重复发送给控制机。
                        handler.client_requests.append(self.request)
                    else:
                        handler.client_requests.append(self.request)

                        print("准备发送向{}数据".format(
                            self.master_request.getpeername()))

                        # 发送数据给对方
                        # 请求数据
                        reply_message = {
                            "size": {
                                "width": 0,
                                "height": 0
                            },
                            "action": "capture",
                            "emit": "full"
                        }

                        # 将数据发送给控制机
                        print("将数据发送给控制机")
                        self.master_send_message(json.dumps(reply_message))

                else:
                    print("无法找到目标机器!")

        if "key" in user_data and not self.is_master and self.is_client:
            # 客户端传过来的按键
            pass

        if "mouse" in user_data and not self.is_master and self.is_client:
            # 客户端传过来的鼠标位置
            pass

    def master_send_message(self, data: str):
        """
        发送消息给控制机
        :param data:
        :return:
        """
        try:
            payload = pack_message(data)
            self.master_request.sendall(payload)
        except BrokenPipeError as bpe:
            print("master_send_message.BrokenPipeError:", bpe)

    def client_send_message(self, payload: bytes):
        """
        发送数据给所有用户机
        :param payload: 控制机传过来的二进制数据
        :return:
        """
        # output: bytearray = self.message.unpack_message(data)
        # print("requests:", self.client_requests)
        for request in self.client_requests:
            try:
                request.sendall(payload)
            except OSError as ose:
                self.client_requests.remove(request)
                print("OSError:(client_request.sendall)", ose)

    def send_message(self):
        """
        发送消息给用户机
        :return:
        """

        message = b''
        while not self.queue.empty():
            message += self.queue.get_nowait()

        presentation = decode_utf8(message, flag='replace', replace_str='?')
        payload = pack_message(presentation)

        try:
            # print("发送数据", self.request)
            self.request.send(payload)

            self.reg_read()
        except BrokenPipeError as bpe:
            print("bpe:", bpe)

    def send_raw_message(self, data: bytes):
        """
        发送裸数据给用户机
        :param data:
        :return:
        """
        try:
            self.request.send(data)
            self.reg_read()
        except BrokenPipeError as bpe:
            print("bpe:", bpe)

    def finish(self):
        if self.master_handler:
            if len(self.master_handler.client_requests) > 0:
                # 将自己从master中删除。
                print("self.master_handler.client_requests",
                      self.master_handler.client_requests)
                self.master_handler.client_requests.remove(self.request)

        print("关闭连接了", self.request)
        self.keep_alive = False