import threading
import socket
import json
import struct
from dcs.tests.requestHandler import RequestHandler
from loguru import logger


def read_bytes(s: 'socket.socket', size: 'int') -> 'bytes':
    data = ''.encode('utf-8')
    while len(data) < size:
        rsp_data = s.recv(size - len(data))
        data += rsp_data
        if len(rsp_data) == 0:
            break
    return data


class Server(threading.Thread):
    def __init__(self, port: 'int'):
        super().__init__()
        self.port: 'int' = port
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket.bind(('', port))
        self.buffer_size = 8 * 1024 * 1024

    def run(self) -> None:
        self.server_socket.listen()
        while True:
            client_socket, _ = self.server_socket.accept()
            request_header_size = struct.unpack("!Q", read_bytes(client_socket, 8))[0]
            request_map = json.JSONDecoder().decode(read_bytes(client_socket, request_header_size).decode("utf-8"))
            # end请求要在主线程处理，不然退出就不会及时响应
            if request_map['action'] == 'end':
                logger.info(f"[REQUEST] end")
                logger.warning("communication over!")
                break
            r = RequestHandler(self, client_socket, request_map)
            r.start()
        self.server_socket.close()
