import hashlib

UUID_MAXSTRSIZE = 37
"""
12345678-0123-5678-0123-567890123456
"""

UUID_INVALID = -2

UUID_UNKNOWN = -1

OFFSET_UUID = 1 << 16
"""
OFFSET_UUID (65536)
"""


TEEWORLDS_NAMESPACE = b'\xe0\x5d\xda\xaa\xc4\xe6\x4c\xfb\xb6\x42\x5d\x48\xe8\x0c\x00\x29'
"""
e05ddaaa-c4e6-4cfb-b642-5d48e80c0029
"""

class DDNetUuid:
    def __init__(self, type_id: int, name: str, uuid: bytes) -> None:
        self.name = name
        self.type_id = type_id
        self.uuid = uuid

class UuidManager:
    def __init__(self) -> None:
        self.uuids: list[DDNetUuid] = []

    def get_index(self, type_id: int) -> int:
        return type_id - OFFSET_UUID

    def get_id(self, type_index: int) -> int:
        return type_index + OFFSET_UUID

    def register_name(self, type_id: int, name: str) -> None:
        """
        Every ddnet ex message has a uuid and a unique type_id which is an
        integer incremented starting from OFFSET_UUID (65536)

        What is sent over the network can also be a type_index which is
        the type_id minus the OFFSET_UUID
        """
        self.uuids.append(DDNetUuid(type_id, name, self.calculate_uuid(name)))

    def get_uuid_by_type(self, type_id: int) -> DDNetUuid:
        return self.uuids[type_id]

    def calculate_uuid(self, name: str) -> bytes:
        md5_hash = hashlib.md5()
        md5_hash.update(TEEWORLDS_NAMESPACE)
        md5_hash.update(name.encode('utf-8'))

        digest = bytearray(md5_hash.digest())

        # set version 3 (UUID is generated by MD5 hashing a namespace identifier and a name)
        digest[6] &= 0x0f
        digest[6] |= 0x30

        # set variant 1 (RFC 4122)
        digest[8] &= 0x3f
        digest[8] |= 0x80

        return bytes(digest)

