#
# Copyright 2016 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""
A simple internal pub/sub event bus with topics and filter-based registration.
"""
import re

import structlog


log = structlog.get_logger()


class _Subscription(object):

    __slots__ = ('bus', 'predicate', 'callback', 'topic')
    def __init__(self, bus, predicate, callback, topic=None):
        self.bus = bus
        self.predicate = predicate
        self.callback = callback
        self.topic = topic


class EventBus(object):

    def __init__(self):
        self.subscriptions = {}  # topic -> list of _Subscription objects
                                 # topic None holds regexp based topic subs.
        self.subs_topic_map = {} # to aid fast lookup when unsubscribing

    def list_subscribers(self, topic=None):
        if topic is None:
            return sum(self.subscriptions.itervalues(), [])
        else:
            if topic in self.subscriptions:
                return self.subscriptions[topic]
            else:
                return []

    @staticmethod
    def _get_topic_key(topic):
        if isinstance(topic, str):
            return topic
        elif hasattr(topic, 'match'):
            return None
        else:
            raise AttributeError('topic not a string nor a compiled regex')

    def subscribe(self, topic, callback, predicate=None):
        """
        Subscribe to given topic with predicate and register the callback
        :param topic: String topic (explicit) or regexp based topic filter.
        :param callback: Callback method with signature def func(topic, msg)
        :param predicate: Optional method/function signature def predicate(msg)
        :return: Subscription object which can be used to unsubscribe
        """
        subscription = _Subscription(self, predicate, callback, topic)
        topic_key = self._get_topic_key(topic)
        self.subscriptions.setdefault(topic_key, []).append(subscription)
        self.subs_topic_map[subscription] = topic_key
        return subscription

    def unsubscribe(self, subscription):
        """
        Remove given subscription
        :param subscription: subscription object as was returned by subscribe
        :return: None
        """
        topic_key = self.subs_topic_map[subscription]
        self.subscriptions[topic_key].remove(subscription)

    def publish(self, topic, msg):
        """
        Publish given message to all subscribers registered with topic taking
        the predicate functions into account.
        :param topic: String topic
        :param msg: Arbitrary python data as message
        :return: None
        """

        def passes(msg, predicate):
            try:
                return predicate(msg)
            except Exception, e:
                return False  # failed predicate function treated as no match

        # lookup subscribers with explicit topic subscriptions
        subscribers = self.subscriptions.get(topic, [])

        # add matching regexp topic subscribers
        subscribers.extend(s for s in self.subscriptions.get(None, [])
                           if s.topic.match(topic))

        for candidate in subscribers:
            predicate = candidate.predicate
            if predicate is None or passes(msg, predicate):
                try:
                    candidate.callback(topic, msg)
                except Exception, e:
                    log.warning('callback-failed', e=e, topic=topic)


default_bus = EventBus()


class EventBusClient(object):
    """
    Primary interface to the EventBus. Usage:

    Publish:
    >>> events = EventBusClient()
    >>> msg = dict(a=1, b='foo')
    >>> events.publish('a.topic', msg)

    Subscribe to get all messages on specific topic:
    >>> def got_event(topic, msg):
    >>>     print topic, ':', msg
    >>> events = EventBusClient()
    >>> events.subscribe('a.topic', got_event)

    Subscribe to get messages matching predicate on specific topic:
    >>> def got_event(topic, msg):
    >>>     print topic, ':', msg
    >>> events = EventBusClient()
    >>> events.subscribe('a.topic', got_event, lambda msg: msg.len() < 100)

    Use a DeferredQueue to buffer incoming messages
    >>> queue = DeferredQueue()
    >>> events = EventBusClient()
    >>> events.subscribe('a.topic', lambda _, msg: queue.put(msg))

    """
    def __init__(self, bus=None):
        """
        Obtain a client interface for the pub/sub event bus.
        :param bus: An optional specific event bus. Inteded for mainly test
        use. If not provided, the process default bus will be used, which is
        the preferred use (a process shall not need more than one bus).
        """
        self.bus = bus or default_bus

    def publish(self, topic, msg):
        """
        Publish given msg to given topic.
        :param topic: String topic
        :param msg: Arbitrary python data as message
        :return: None
        """
        self.bus.publish(topic, msg)

    def subscribe(self, topic, callback, predicate=None):
        """
        Subscribe to given topic with predicate and register the callback
        :param topic: String topic (explicit) or regexp based topic filter.
        :param callback: Callback method with signature def func(topic, msg)
        :param predicate: Optional method/function with signature
        def predicate(msg)
        :return: Subscription object which can be used to unsubscribe
        """
        return self.bus.subscribe(topic, callback, predicate)

    def unsubscribe(self, subscription):
        """
        Remove given subscription
        :param subscription: subscription object as was returned by subscribe
        :return: None
        """
        return self.bus.unsubscribe(subscription)

    def list_subscribers(self, topic=None):
        """
        Return list of subscribers. If topci is provided, it is filtered for
        those subscribing to the topic.
        :param topic: Optional topic
        :return: List of subscriptions
        """
        return self.bus.list_subscribers(topic)
