# Path: cbus/protocol/confirm_packet.py
# class ConfirmationPacket(SpecialServerPacket):
#     """
#     Confirmation special packet.  Serial interface guide s4.3.3.3 p32
#     """
# 
#     def __init__(self, code: bytes, success: bool):
#         super(ConfirmationPacket, self).__init__()
# 
#         self._code = code[:1]
#         if self._code not in CONFIRMATION_CODES:
#             raise ValueError('confirmation code is not valid')
# 
#         self._success = bool(success)
# 
#     def encode(self) -> bytes:
#         return self._code + (b'.' if self._success else b'#')
# 
#     @property
#     def code(self) -> bytes:
#         return self._code
# 
#     @property
#     def success(self) -> bool:
#         return self._success
# 
#     def __repr__(self):
#         return (f'{self.__class__.__name__}('
#                 f'code={self.code!r}, success={self.success})')
# 
# Path: cbus/protocol/error_packet.py
# class PCIErrorPacket(SpecialServerPacket):
# 
#     def __init__(self):
#         super(PCIErrorPacket, self).__init__()
# 
#     def encode(self) -> bytes:
#         return b'!'
# 
#     def __repr__(self):
#         return f'{self.__class__.__name__}()'
# 
# Path: cbus/protocol/po_packet.py
# class PowerOnPacket(SpecialServerPacket):
# 
#     def __init__(self):
#         super(PowerOnPacket, self).__init__()
# 
#     def encode(self):
#         # We send two "Power On" bytes, like C-Bus, because the first one
#         # could be lost because of bit errors.
#         return b'++'
# 
# Path: cbus/protocol/reset_packet.py
# class ResetPacket(SpecialClientPacket):
# 
#     def __init__(self):
#         super(ResetPacket, self).__init__()
# 
#     def encode(self):
#         return b'~'
# 
# Path: cbus/protocol/scs_packet.py
# class SmartConnectShortcutPacket(SpecialClientPacket):
# 
#     def __init__(self):
#         super(SmartConnectShortcutPacket, self).__init__()
# 
#     def encode(self) -> bytes:
#         return b'|'
# 
# Path: tests/utils.py
# class CBusTestCase(unittest.TestCase):
# 
#     def decode_packet(
#             self, data: bytes,
#             checksum: bool = True,
#             strict: bool = True,
#             from_pci: bool = True,
#             expected_position: Optional[int] = None) -> Optional[BasePacket]:
#         """
#         Decodes a packet, and validates that the buffer position has consumed
#         the packet.
# 
#         See ``cbus.packet.decode_packet`` for details.
# 
#         :param expected_position: If None (default), expect to consume the
#                                   entire input data. Otherwise, an integer
#                                   number of bytes that were expected to be
#                                   consumed.
#         :return: The parsed packet, or None if no packet was parsed.
#         """
#         if expected_position is None:
#             expected_position = len(data)
# 
#         packet, position = decode_packet(data, checksum, strict, from_pci)
#         self.assertEqual(
#             expected_position, position,
#             f'Expected to parse {expected_position} bytes of input data: '
#             f'{data!r}')
# 
#         return packet
# 
#     def decode_pm(
#             self, data: bytes,
#             checksum: bool = True,
#             strict: bool = True,
#             from_pci: bool = True,
#             expected_position: Optional[int] = None)\
#             -> PointToMultipointPacket:
#         """Decodes and asserts a packet is PointToMultipointPacket."""
# 
#         p = self.decode_packet(
#             data, checksum, strict, from_pci, expected_position)
#         self.assertIsInstance(p, PointToMultipointPacket)
#         return p
# 
#     def decode_pp(
#             self, data: bytes,
#             checksum: bool = True,
#             strict: bool = True,
#             from_pci: bool = True,
#             expected_position: Optional[int] = None) \
#             -> PointToPointPacket:
#         """Decodes and asserts a packet is PointToPointPacket."""
# 
#         p = self.decode_packet(
#             data, checksum, strict, from_pci, expected_position)
#         self.assertIsInstance(p, PointToPointPacket)
#         return p


from typing import Optional
from cbus.protocol.confirm_packet import ConfirmationPacket
from cbus.protocol.error_packet import PCIErrorPacket
from cbus.protocol.po_packet import PowerOnPacket
from cbus.protocol.reset_packet import ResetPacket
from cbus.protocol.scs_packet import SmartConnectShortcutPacket
from .utils import CBusTestCase
import unittest
from __future__ import absolute_import




class SpecialPacketTest(CBusTestCase):

    def check_packet_type(self, data: bytes,
                          typ=None,
                          checksum: bool = True,
                          strict: bool = True,
                          from_pci: bool = True,
                          expected_position: Optional[int] = None):
        p = self.decode_packet(
            data, checksum, strict, from_pci, expected_position)

        if typ is None:
            self.assertIsNone(p)
        else:
            self.assertIsInstance(p, typ)

        return p

    # Packets from PCI
    def test_power_on(self):
        self.check_packet_type(b'++', PowerOnPacket, expected_position=1)
        self.assertEqual(b'++', PowerOnPacket().encode_packet())

    def test_error(self):
        self.check_packet_type(b'!', PCIErrorPacket, expected_position=1)

# Path: cbus/protocol/confirm_packet.py
# class ConfirmationPacket(SpecialServerPacket):
#     """
#     Confirmation special packet.  Serial interface guide s4.3.3.3 p32
#     """
# 
#     def __init__(self, code: bytes, success: bool):
#         super(ConfirmationPacket, self).__init__()
# 
#         self._code = code[:1]
#         if self._code not in CONFIRMATION_CODES:
#             raise ValueError('confirmation code is not valid')
# 
#         self._success = bool(success)
# 
#     def encode(self) -> bytes:
#         return self._code + (b'.' if self._success else b'#')
# 
#     @property
#     def code(self) -> bytes:
#         return self._code
# 
#     @property
#     def success(self) -> bool:
#         return self._success
# 
#     def __repr__(self):
#         return (f'{self.__class__.__name__}('
#                 f'code={self.code!r}, success={self.success})')
# 
# Path: cbus/protocol/error_packet.py
# class PCIErrorPacket(SpecialServerPacket):
# 
#     def __init__(self):
#         super(PCIErrorPacket, self).__init__()
# 
#     def encode(self) -> bytes:
#         return b'!'
# 
#     def __repr__(self):
#         return f'{self.__class__.__name__}()'
# 
# Path: cbus/protocol/po_packet.py
# class PowerOnPacket(SpecialServerPacket):
# 
#     def __init__(self):
#         super(PowerOnPacket, self).__init__()
# 
#     def encode(self):
#         # We send two "Power On" bytes, like C-Bus, because the first one
#         # could be lost because of bit errors.
#         return b'++'
# 
# Path: cbus/protocol/reset_packet.py
# class ResetPacket(SpecialClientPacket):
# 
#     def __init__(self):
#         super(ResetPacket, self).__init__()
# 
#     def encode(self):
#         return b'~'
# 
# Path: cbus/protocol/scs_packet.py
# class SmartConnectShortcutPacket(SpecialClientPacket):
# 
#     def __init__(self):
#         super(SmartConnectShortcutPacket, self).__init__()
# 
#     def encode(self) -> bytes:
#         return b'|'
# 
# Path: tests/utils.py
# class CBusTestCase(unittest.TestCase):
# 
#     def decode_packet(
#             self, data: bytes,
#             checksum: bool = True,
#             strict: bool = True,
#             from_pci: bool = True,
#             expected_position: Optional[int] = None) -> Optional[BasePacket]:
#         """
#         Decodes a packet, and validates that the buffer position has consumed
#         the packet.
# 
#         See ``cbus.packet.decode_packet`` for details.
# 
#         :param expected_position: If None (default), expect to consume the
#                                   entire input data. Otherwise, an integer
#                                   number of bytes that were expected to be
#                                   consumed.
#         :return: The parsed packet, or None if no packet was parsed.
#         """
#         if expected_position is None:
#             expected_position = len(data)
# 
#         packet, position = decode_packet(data, checksum, strict, from_pci)
#         self.assertEqual(
#             expected_position, position,
#             f'Expected to parse {expected_position} bytes of input data: '
#             f'{data!r}')
# 
#         return packet
# 
#     def decode_pm(
#             self, data: bytes,
#             checksum: bool = True,
#             strict: bool = True,
#             from_pci: bool = True,
#             expected_position: Optional[int] = None)\
#             -> PointToMultipointPacket:
#         """Decodes and asserts a packet is PointToMultipointPacket."""
# 
#         p = self.decode_packet(
#             data, checksum, strict, from_pci, expected_position)
#         self.assertIsInstance(p, PointToMultipointPacket)
#         return p
# 
#     def decode_pp(
#             self, data: bytes,
#             checksum: bool = True,
#             strict: bool = True,
#             from_pci: bool = True,
#             expected_position: Optional[int] = None) \
#             -> PointToPointPacket:
#         """Decodes and asserts a packet is PointToPointPacket."""
# 
#         p = self.decode_packet(
#             data, checksum, strict, from_pci, expected_position)
#         self.assertIsInstance(p, PointToPointPacket)
#         return p


# Path: tests/test_special_packet.py
from typing import Optional
from cbus.protocol.confirm_packet import ConfirmationPacket
from cbus.protocol.error_packet import PCIErrorPacket
from cbus.protocol.po_packet import PowerOnPacket
from cbus.protocol.reset_packet import ResetPacket
from cbus.protocol.scs_packet import SmartConnectShortcutPacket
from .utils import CBusTestCase
import unittest

from __future__ import absolute_import




class SpecialPacketTest(CBusTestCase):

    def check_packet_type(self, data: bytes,
                          typ=None,
                          checksum: bool = True,
                          strict: bool = True,
                          from_pci: bool = True,
                          expected_position: Optional[int] = None):
        p = self.decode_packet(
            data, checksum, strict, from_pci, expected_position)

        if typ is None:
            self.assertIsNone(p)
        else:
            self.assertIsInstance(p, typ)

        return p

    # Packets from PCI
    def test_power_on(self):
        self.check_packet_type(b'++', PowerOnPacket, expected_position=1)
        self.assertEqual(b'++', PowerOnPacket().encode_packet())

    def test_error(self):
        self.check_packet_type(b'!', PCIErrorPacket, expected_position=1)

        self.assertEqual(b'!', PCIErrorPacket().encode_packet())