import threading
import time

from core.aochat.bot import Bot
from core.aochat.client_packets import Ping
from core.aochat.delay_queue import DelayQueue


class Conn(Bot):
    def __init__(self, _id, failure_callback):
        super().__init__()
        self.id = _id
        self.packet_queue = DelayQueue(2, 2.5)
        self.packet_last_received_timestamp = time.time()
        self.failure_callback = failure_callback
        self.send_lock = threading.Lock()

    def read_packet(self, max_delay_time=1):
        self.check_outgoing_message_queue()
        packet = super().read_packet(max_delay_time)
        if not packet:
            time_since = time.time() - self.packet_last_received_timestamp
            if time_since > 90:
                self.logger.error(f"no packet received in 90 seconds for conn {self.id}")
                self.failure_callback()
            if time_since > 60:
                self.send_packet(Ping("igncore_aochat"))
        else:
            self.packet_last_received_timestamp = time.time()
        return packet

    def send_packet(self, packet):
        # synchronize sending packets
        # noinspection PyBroadException
        try:
            with self.send_lock:
                super().send_packet(packet)
        except Exception as e:
            self.failure_callback()

    def add_packet_to_queue(self, packet):
        self.packet_queue.enqueue(packet)
        self.check_outgoing_message_queue()

    def check_outgoing_message_queue(self):
        # check packet queue for outgoing packets
        outgoing_packet = self.packet_queue.dequeue()
        while outgoing_packet:
            self.send_packet(outgoing_packet)
            outgoing_packet = self.packet_queue.dequeue()

        num_messages = len(self.packet_queue)
        if num_messages > 30:
            self.logger.warning("automatically clearing outgoing message queue (%d messages)" % num_messages)
            self.packet_queue.clear()
        # elif num_messages > 10:
            # self.logger.warning("%d messages in outgoing message queue" % num_messages)

    def __str__(self):
        return self.id

    def __repr__(self):
        return self.__str__()
