# Path: coolamqp/framing/base.py
# class AMQPFrame(object):  # base class for framing
#     __slots__ = ('channel', )
#     FRAME_TYPE = None  # override me!
# 
#     def __init__(self, channel):  # type: (int) -> None
#         self.channel = channel
# 
#     def write_to(self, buf):  # type: (io.BinaryIO) -> None
#         """
#         Write a complete frame to buffer
# 
#         This writes type and channel ID.
#         """
#         # DO NOT UNCOMMENT buf.write(struct.pack('!BH', self.FRAME_TYPE, self.channel))
#         raise NotImplementedError(
#             'Please write the frame type and channel in child classes, its faster that way ')
# 
#     @staticmethod
#     def unserialize(channel, payload_as_buffer):
#         """
#         Unserialize from a buffer.
#         Buffer starts at frame's own payload - type, channel and size was already obtained.
#         Payload does not contain FRAME_EMD.
#         AMQPHeartbeatFrame does not have to implement this.
#         """
#         raise NotImplementedError('Override me')
# 
#     def get_size(self):  # type: () -> int
#         """
#         Return size of this frame, in bytes, from frame type to frame_end
#         :return: int
#         """
#         raise NotImplementedError('Override me')
# 
#     def __str__(self):  # type: () -> str
#         return 'AMQPFrame(%s)' % (self.channel,)
# 
# Path: coolamqp/framing/definitions.py
# FRAME_METHOD = 1
# 
# FRAME_HEARTBEAT = 8
# 
# FRAME_BODY = 3
# 
# FRAME_HEADER = 2
# 
# FRAME_END = 206
# 
# IDENT_TO_METHOD = {
#     (10, 60): ConnectionBlocked,
#     (10, 50): ConnectionClose,
#     (10, 51): ConnectionCloseOk,
#     (10, 40): ConnectionOpen,
#     (10, 41): ConnectionOpenOk,
#     (10, 10): ConnectionStart,
#     (10, 20): ConnectionSecure,
#     (10, 11): ConnectionStartOk,
#     (10, 21): ConnectionSecureOk,
#     (10, 30): ConnectionTune,
#     (10, 31): ConnectionTuneOk,
#     (10, 61): ConnectionUnblocked,
#     (20, 40): ChannelClose,
#     (20, 41): ChannelCloseOk,
#     (20, 20): ChannelFlow,
#     (20, 21): ChannelFlowOk,
#     (20, 10): ChannelOpen,
#     (20, 11): ChannelOpenOk,
#     (40, 30): ExchangeBind,
#     (40, 31): ExchangeBindOk,
#     (40, 10): ExchangeDeclare,
#     (40, 20): ExchangeDelete,
#     (40, 11): ExchangeDeclareOk,
#     (40, 21): ExchangeDeleteOk,
#     (40, 40): ExchangeUnbind,
#     (40, 51): ExchangeUnbindOk,
#     (50, 20): QueueBind,
#     (50, 21): QueueBindOk,
#     (50, 10): QueueDeclare,
#     (50, 40): QueueDelete,
#     (50, 11): QueueDeclareOk,
#     (50, 41): QueueDeleteOk,
#     (50, 30): QueuePurge,
#     (50, 31): QueuePurgeOk,
#     (50, 50): QueueUnbind,
#     (50, 51): QueueUnbindOk,
#     (60, 80): BasicAck,
#     (60, 20): BasicConsume,
#     (60, 30): BasicCancel,
#     (60, 21): BasicConsumeOk,
#     (60, 31): BasicCancelOk,
#     (60, 60): BasicDeliver,
#     (60, 70): BasicGet,
#     (60, 71): BasicGetOk,
#     (60, 72): BasicGetEmpty,
#     (60, 120): BasicNack,
#     (60, 40): BasicPublish,
#     (60, 10): BasicQos,
#     (60, 11): BasicQosOk,
#     (60, 50): BasicReturn,
#     (60, 90): BasicReject,
#     (60, 100): BasicRecoverAsync,
#     (60, 110): BasicRecover,
#     (60, 111): BasicRecoverOk,
#     (90, 20): TxCommit,
#     (90, 21): TxCommitOk,
#     (90, 30): TxRollback,
#     (90, 31): TxRollbackOk,
#     (90, 10): TxSelect,
#     (90, 11): TxSelectOk,
#     (85, 10): ConfirmSelect,
#     (85, 11): ConfirmSelectOk,
# }
# 
# CLASS_ID_TO_CONTENT_PROPERTY_LIST = {
#     60: BasicContentPropertyList,
# }
# 
# FRAME_END_BYTE = b'\xce'


import struct
import six
from coolamqp.framing.base import AMQPFrame
from coolamqp.framing.definitions import FRAME_METHOD, FRAME_HEARTBEAT, \
    FRAME_BODY, FRAME_HEADER, FRAME_END, \
    IDENT_TO_METHOD, CLASS_ID_TO_CONTENT_PROPERTY_LIST, FRAME_END_BYTE
    @classmethod
    def unserialize(cls, channel, payload_as_buffer):
        clsmet = STRUCT_HH.unpack_from(payload_as_buffer, 0)

        try:
            method_payload_class = IDENT_TO_METHOD[clsmet]
            payload = method_payload_class.from_buffer(payload_as_buffer, 4)
        except KeyError:
            raise ValueError('Invalid class %s method %s' % clsmet)
        else:
            return cls(channel, payload)

    def get_size(self):  # type: () -> int
        # frame_header = (method(1) + channel(2) + length(4) + class(2) + method(2) + payload(N) + frame_end(1))
        return 12 + self.payload.get_size()


class AMQPHeaderFrame(AMQPFrame):
    """
    A frame containing a message header

    :param channel: channel ID
    :type channel: int
    :param class_id: class ID
    :type class_id: int
    :param weight: weight (lol wut?)
    :param body_size: size of the body to follow
    :param properties: a suitable AMQPContentPropertyList instance
    """
    __slots__ = ('class_id', 'weight', 'body_size', 'properties')

# Path: coolamqp/framing/base.py
# class AMQPFrame(object):  # base class for framing
#     __slots__ = ('channel', )
#     FRAME_TYPE = None  # override me!
# 
#     def __init__(self, channel):  # type: (int) -> None
#         self.channel = channel
# 
#     def write_to(self, buf):  # type: (io.BinaryIO) -> None
#         """
#         Write a complete frame to buffer
# 
#         This writes type and channel ID.
#         """
#         # DO NOT UNCOMMENT buf.write(struct.pack('!BH', self.FRAME_TYPE, self.channel))
#         raise NotImplementedError(
#             'Please write the frame type and channel in child classes, its faster that way ')
# 
#     @staticmethod
#     def unserialize(channel, payload_as_buffer):
#         """
#         Unserialize from a buffer.
#         Buffer starts at frame's own payload - type, channel and size was already obtained.
#         Payload does not contain FRAME_EMD.
#         AMQPHeartbeatFrame does not have to implement this.
#         """
#         raise NotImplementedError('Override me')
# 
#     def get_size(self):  # type: () -> int
#         """
#         Return size of this frame, in bytes, from frame type to frame_end
#         :return: int
#         """
#         raise NotImplementedError('Override me')
# 
#     def __str__(self):  # type: () -> str
#         return 'AMQPFrame(%s)' % (self.channel,)
# 
# Path: coolamqp/framing/definitions.py
# FRAME_METHOD = 1
# 
# FRAME_HEARTBEAT = 8
# 
# FRAME_BODY = 3
# 
# FRAME_HEADER = 2
# 
# FRAME_END = 206
# 
# IDENT_TO_METHOD = {
#     (10, 60): ConnectionBlocked,
#     (10, 50): ConnectionClose,
#     (10, 51): ConnectionCloseOk,
#     (10, 40): ConnectionOpen,
#     (10, 41): ConnectionOpenOk,
#     (10, 10): ConnectionStart,
#     (10, 20): ConnectionSecure,
#     (10, 11): ConnectionStartOk,
#     (10, 21): ConnectionSecureOk,
#     (10, 30): ConnectionTune,
#     (10, 31): ConnectionTuneOk,
#     (10, 61): ConnectionUnblocked,
#     (20, 40): ChannelClose,
#     (20, 41): ChannelCloseOk,
#     (20, 20): ChannelFlow,
#     (20, 21): ChannelFlowOk,
#     (20, 10): ChannelOpen,
#     (20, 11): ChannelOpenOk,
#     (40, 30): ExchangeBind,
#     (40, 31): ExchangeBindOk,
#     (40, 10): ExchangeDeclare,
#     (40, 20): ExchangeDelete,
#     (40, 11): ExchangeDeclareOk,
#     (40, 21): ExchangeDeleteOk,
#     (40, 40): ExchangeUnbind,
#     (40, 51): ExchangeUnbindOk,
#     (50, 20): QueueBind,
#     (50, 21): QueueBindOk,
#     (50, 10): QueueDeclare,
#     (50, 40): QueueDelete,
#     (50, 11): QueueDeclareOk,
#     (50, 41): QueueDeleteOk,
#     (50, 30): QueuePurge,
#     (50, 31): QueuePurgeOk,
#     (50, 50): QueueUnbind,
#     (50, 51): QueueUnbindOk,
#     (60, 80): BasicAck,
#     (60, 20): BasicConsume,
#     (60, 30): BasicCancel,
#     (60, 21): BasicConsumeOk,
#     (60, 31): BasicCancelOk,
#     (60, 60): BasicDeliver,
#     (60, 70): BasicGet,
#     (60, 71): BasicGetOk,
#     (60, 72): BasicGetEmpty,
#     (60, 120): BasicNack,
#     (60, 40): BasicPublish,
#     (60, 10): BasicQos,
#     (60, 11): BasicQosOk,
#     (60, 50): BasicReturn,
#     (60, 90): BasicReject,
#     (60, 100): BasicRecoverAsync,
#     (60, 110): BasicRecover,
#     (60, 111): BasicRecoverOk,
#     (90, 20): TxCommit,
#     (90, 21): TxCommitOk,
#     (90, 30): TxRollback,
#     (90, 31): TxRollbackOk,
#     (90, 10): TxSelect,
#     (90, 11): TxSelectOk,
#     (85, 10): ConfirmSelect,
#     (85, 11): ConfirmSelectOk,
# }
# 
# CLASS_ID_TO_CONTENT_PROPERTY_LIST = {
#     60: BasicContentPropertyList,
# }
# 
# FRAME_END_BYTE = b'\xce'


# Path: coolamqp/framing/frames.py
import struct
import six
from coolamqp.framing.base import AMQPFrame
from coolamqp.framing.definitions import FRAME_METHOD, FRAME_HEARTBEAT, \
    FRAME_BODY, FRAME_HEADER, FRAME_END, \
    IDENT_TO_METHOD, CLASS_ID_TO_CONTENT_PROPERTY_LIST, FRAME_END_BYTE

    @classmethod
    def unserialize(cls, channel, payload_as_buffer):
        clsmet = STRUCT_HH.unpack_from(payload_as_buffer, 0)

        try:
            method_payload_class = IDENT_TO_METHOD[clsmet]
            payload = method_payload_class.from_buffer(payload_as_buffer, 4)
        except KeyError:
            raise ValueError('Invalid class %s method %s' % clsmet)
        else:
            return cls(channel, payload)

    def get_size(self):  # type: () -> int
        # frame_header = (method(1) + channel(2) + length(4) + class(2) + method(2) + payload(N) + frame_end(1))
        return 12 + self.payload.get_size()


class AMQPHeaderFrame(AMQPFrame):
    """
    A frame containing a message header

    :param channel: channel ID
    :type channel: int
    :param class_id: class ID
    :type class_id: int
    :param weight: weight (lol wut?)
    :param body_size: size of the body to follow
    :param properties: a suitable AMQPContentPropertyList instance
    """
    __slots__ = ('class_id', 'weight', 'body_size', 'properties')

    FRAME_TYPE = FRAME_HEADER