"""Pr Packet"""

import sys

if sys.version_info >= (3, 11):
  from typing import Self
else:
  from typing_extensions import Self

from layrz_protocol.utils.crc import calculate_crc
from layrz_protocol.utils.exceptions import CrcException, MalformedException

from .base import ClientPacket


class PrPacket(ClientPacket):
  """Pr packet definition"""

  @staticmethod
  def from_packet(raw: str) -> 'PrPacket':
    """Create a packet from raw data"""
    if not raw.startswith('<Pr>') or not raw.endswith('</Pr>'):
      raise MalformedException('Invalid packet definition, should be <Pr>...</Pr>')

    parts = raw[4:-5].split(';')
    if len(parts) != 1:
      raise MalformedException('Invalid packet definition, should have 3 parts')

    received_crc: int
    try:
      received_crc = int(parts[-1], base=16)
    except ValueError:
      received_crc = 0

    calculated_crc: int = calculate_crc(f'{";".join(parts[:-1])};'.encode())

    if received_crc != calculated_crc:
      raise CrcException('Invalid CRC', received=received_crc, calculated=calculated_crc)

    return PrPacket()

  def to_packet(self: Self) -> str:
    """Convert packet to raw data"""
    raw = ';'
    crc = str(hex(calculate_crc(f'{raw}'.encode())))[2:].upper().zfill(4)
    return f'<Pr>{raw}{crc}</Pr>'

  def __str__(self: Self) -> str:
    """String representation of the packet"""
    return self.to_packet()
