# Path: snakemq/exceptions.py
# class SnakeMQBrokenMessage(SnakeMQBrokenFormat):
#     """
#     Received message has wrong structure.
#     """
#     pass
# 
# class SnakeMQException(Exception):
#     pass
# 
# class SnakeMQIncompatibleProtocol(SnakeMQException):
#     """
#     Remote side has incompatible protocol version.
#     """
#     pass
# 
# class SnakeMQNoIdent(SnakeMQException):
#     """
#     Remote side did not identified itself.
#     """
#     pass
# 
# class NoConnection(SnakeMQException):
#     pass
# 
# Path: snakemq/queues.py
# class QueuesManager(object):
#     def __init__(self, storage):
#         """
#         :param storage: None or persistent storage
#         """
#         assert (storage is None) or isinstance(storage, QueuesStorageBase)
#         self.storage = storage
#         self.queues = {}  #: name:Queue
#         self.log = logging.getLogger("snakemq.queuesmanager")
#         if storage:
#             self.load_from_storage()
#             self.log.debug("queues in storage: %i" % len(self.queues))
# 
#         self.on_item_drop = Callback()  #: ``func(queue_name, item_uuid)``
# 
#     ####################################################
# 
#     def load_from_storage(self):
#         for queue_name in self.storage.get_queues():
#             self.get_queue(queue_name)
# 
#     ####################################################
# 
#     def get_queue(self, queue_name):
#         """
#         :return: Queue
#         """
#         if queue_name in self.queues:
#             queue = self.queues[queue_name]
#         else:
#             queue = Queue(queue_name, self)
#             self.queues[queue_name] = queue
#         return queue
# 
#     ####################################################
# 
#     def cleanup(self):
#         """
#         remove empty queues
#         """
#         for queue_name, queue in self.queues.items():
#             if not queue:
#                 del self.queues[queue_name]
# 
#     ####################################################
# 
#     def close(self):
#         """
#         Delete queues and close persistent storage.
#         """
#         self.queues.clear()
#         if self.storage:
#             self.storage.close()
#             self.storage = None
# 
#     ####################################################
# 
#     def collect_garbage(self):
#         """
#         Call this periodically to remove obsolete items and empty queues.
#         """
#         # TODO
# 
#     ####################################################
# 
#     def __len__(self):
#         return len(self.queues)
# 
# Path: snakemq/callbacks.py
# class Callback(object):
#     def __init__(self):
#         self.callbacks = []
# 
#     ####################################################
# 
#     def add(self, func):
#         self.callbacks.append(func)
# 
#     ####################################################
# 
#     def remove(self, func):
#         self.callbacks.remove(func)
# 
#     ####################################################
# 
#     def __call__(self, *args, **kwargs):
#         for callback in self.callbacks:
#             callback(*args, **kwargs)


import struct
import logging
import threading
import re
import time
import snakemq.version
from snakemq.exceptions import (SnakeMQBrokenMessage, SnakeMQException,
                                SnakeMQIncompatibleProtocol, SnakeMQNoIdent,
                                NoConnection)
from snakemq.queues import QueuesManager
from snakemq.message import Message
from snakemq.callbacks import Callback
ENCODING = "utf-8"

#############################################################################
#############################################################################

class Messaging(object):
    def __init__(self, identifier, domain, packeter, queues_storage=None):
        """
        :param identifier: peer identifier
        :param domain: currently unused
        :param packeter: :class:`~snakemq.packeter.Packeter`
        :param queues_storage: :class:`~snakemq.storage.QueuesStorageBase`
        """
        self.identifier = identifier[:MAX_IDENT_LENGTH]
        self.domain = domain
        self.packeter = packeter
        self.queues_manager = QueuesManager(queues_storage)
        self.log = logging.getLogger("snakemq.messaging")

        #: time to ping, in seconds (None = no keepalive)
        self.keepalive_interval = None
        self.keepalive_wait = 0.5  #: wait for pong, in seconds

        #{ callbacks
        self.on_error = Callback()  #: ``func(conn_id, exception)``
        self.on_message_recv = Callback()  #: ``func(conn_id, ident, message)``
        self.on_message_sent = Callback()  #: ``func(conn_id, ident, message_uuid)``
        #: ``func(ident, message_uuid)``
        #: Called when the message is dropped from the queue due to the TTL
        #: timeout.

# Path: snakemq/exceptions.py
# class SnakeMQBrokenMessage(SnakeMQBrokenFormat):
#     """
#     Received message has wrong structure.
#     """
#     pass
# 
# class SnakeMQException(Exception):
#     pass
# 
# class SnakeMQIncompatibleProtocol(SnakeMQException):
#     """
#     Remote side has incompatible protocol version.
#     """
#     pass
# 
# class SnakeMQNoIdent(SnakeMQException):
#     """
#     Remote side did not identified itself.
#     """
#     pass
# 
# class NoConnection(SnakeMQException):
#     pass
# 
# Path: snakemq/queues.py
# class QueuesManager(object):
#     def __init__(self, storage):
#         """
#         :param storage: None or persistent storage
#         """
#         assert (storage is None) or isinstance(storage, QueuesStorageBase)
#         self.storage = storage
#         self.queues = {}  #: name:Queue
#         self.log = logging.getLogger("snakemq.queuesmanager")
#         if storage:
#             self.load_from_storage()
#             self.log.debug("queues in storage: %i" % len(self.queues))
# 
#         self.on_item_drop = Callback()  #: ``func(queue_name, item_uuid)``
# 
#     ####################################################
# 
#     def load_from_storage(self):
#         for queue_name in self.storage.get_queues():
#             self.get_queue(queue_name)
# 
#     ####################################################
# 
#     def get_queue(self, queue_name):
#         """
#         :return: Queue
#         """
#         if queue_name in self.queues:
#             queue = self.queues[queue_name]
#         else:
#             queue = Queue(queue_name, self)
#             self.queues[queue_name] = queue
#         return queue
# 
#     ####################################################
# 
#     def cleanup(self):
#         """
#         remove empty queues
#         """
#         for queue_name, queue in self.queues.items():
#             if not queue:
#                 del self.queues[queue_name]
# 
#     ####################################################
# 
#     def close(self):
#         """
#         Delete queues and close persistent storage.
#         """
#         self.queues.clear()
#         if self.storage:
#             self.storage.close()
#             self.storage = None
# 
#     ####################################################
# 
#     def collect_garbage(self):
#         """
#         Call this periodically to remove obsolete items and empty queues.
#         """
#         # TODO
# 
#     ####################################################
# 
#     def __len__(self):
#         return len(self.queues)
# 
# Path: snakemq/callbacks.py
# class Callback(object):
#     def __init__(self):
#         self.callbacks = []
# 
#     ####################################################
# 
#     def add(self, func):
#         self.callbacks.append(func)
# 
#     ####################################################
# 
#     def remove(self, func):
#         self.callbacks.remove(func)
# 
#     ####################################################
# 
#     def __call__(self, *args, **kwargs):
#         for callback in self.callbacks:
#             callback(*args, **kwargs)


# Path: snakemq/messaging.py
import struct
import logging
import threading
import re
import time
import snakemq.version
from snakemq.exceptions import (SnakeMQBrokenMessage, SnakeMQException,
                                SnakeMQIncompatibleProtocol, SnakeMQNoIdent,
                                NoConnection)
from snakemq.queues import QueuesManager
from snakemq.message import Message
from snakemq.callbacks import Callback

ENCODING = "utf-8"

#############################################################################
#############################################################################

class Messaging(object):
    def __init__(self, identifier, domain, packeter, queues_storage=None):
        """
        :param identifier: peer identifier
        :param domain: currently unused
        :param packeter: :class:`~snakemq.packeter.Packeter`
        :param queues_storage: :class:`~snakemq.storage.QueuesStorageBase`
        """
        self.identifier = identifier[:MAX_IDENT_LENGTH]
        self.domain = domain
        self.packeter = packeter
        self.queues_manager = QueuesManager(queues_storage)
        self.log = logging.getLogger("snakemq.messaging")

        #: time to ping, in seconds (None = no keepalive)
        self.keepalive_interval = None
        self.keepalive_wait = 0.5  #: wait for pong, in seconds

        #{ callbacks
        self.on_error = Callback()  #: ``func(conn_id, exception)``
        self.on_message_recv = Callback()  #: ``func(conn_id, ident, message)``
        self.on_message_sent = Callback()  #: ``func(conn_id, ident, message_uuid)``
        #: ``func(ident, message_uuid)``
        #: Called when the message is dropped from the queue due to the TTL
        #: timeout.

        self.on_message_drop = Callback()