from MAXCube import MAXCube
from MAXPacket import MAXPacket, MAXPacketFactory, MAXPairPingPacket, MAXPairPongPacket, MAXAckPacket, \
    MAXResetPacket, MAXWakeUpPacket, MAXSetGroupIdPacket

from time import sleep
from enum import Enum


class HandshakeState(Enum):
    PING_RECEIVED = 1
    PONG_SENT = 2
    PONG_ACK = 3
    GROUP_ID_SENT = 4
    GROUP_ID_ACK = 5


class Handshake:
    def __init__(self, partner_addr, dev_type):
        self.partner_addr = partner_addr
        self.dev_type = dev_type
        self.state: HandshakeState = HandshakeState.PING_RECEIVED


class MAXPacketHandler:
    def __init__(self, cube: MAXCube):
        self.cube = cube
        self.quit_flag = False
        self.handshakes = []

    def handle_msg(self, pkt: MAXPacket):
        print(pkt.to_string())
        if pkt.dest_address == self.cube.addr or pkt.dest_address == "000000":
            if isinstance(pkt, MAXPairPingPacket):
                handshake = Handshake(pkt.sender_address, pkt.device_type)
                self.handshakes.append(handshake)
                pong = MAXPairPongPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr,
                                         dest_address=pkt.sender_address, group_id="00")
                pong_str = pong.serialize()
                print(pong.to_string())
                self.cube.request(pong_str)
                handshake.state = HandshakeState.PONG_SENT
            elif isinstance(pkt, MAXAckPacket):
                cur_handshake: Handshake = None
                for handshake in self.handshakes:
                    if handshake.partner_addr == pkt.sender_address:
                        cur_handshake = handshake
                        break
                if cur_handshake is not None:
                    if cur_handshake.state == HandshakeState.PONG_SENT:
                        cur_handshake.state = HandshakeState.PONG_ACK
                        print(pkt.to_string())
                        if cur_handshake.dev_type == "05":
                            # Handshake is finished
                            print("Paired device with addr={} and type={}".format(cur_handshake.partner_addr,
                                                                                  cur_handshake.dev_type))
                            self.handshakes.remove(cur_handshake)
                        else:
                            set_group_id = MAXSetGroupIdPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr,
                                             dest_address=pkt.sender_address, group_id="00")
                            set_group_id_str = set_group_id.serialize()
                            print(set_group_id_str)
                            self.cube.request(set_group_id_str)
                            cur_handshake.state = HandshakeState.GROUP_ID_SENT
                    if cur_handshake.state == HandshakeState.GROUP_ID_SENT:
                        cur_handshake.state = HandshakeState.GROUP_ID_ACK

        else:
            print("Paket is not ours!")

    def receive_loop(self):
        while not self.quit_flag and self.cube.is_connected():
            resp = self.cube.response()
            if resp is not None and resp[0:1] == "Z":
                pkt = MAXPacketFactory.create_packet(resp)
                self.handle_msg(pkt)


            sleep(0.1)