import gc
import sys
import time

import blinker

from nose.tools import assert_raises


jython = sys.platform.startswith('java')
pypy = hasattr(sys, 'pypy_version_info')

try:
    from _test_async import test_send_async
except (SyntaxError, ImportError):
    pass


def collect_acyclic_refs():
    # cpython releases these immediately without a collection
    if jython or pypy:
        gc.collect()
    if jython:
        time.sleep(0.1)


class Sentinel(list):
    """A signal receipt accumulator."""

    def make_receiver(self, key):
        """Return a generic signal receiver function logging as *key*

        When connected to a signal, appends (key, sender, kw) to the Sentinel.

        """
        def receiver(*sentby, **kw):
            self.append((key, sentby[0], kw))
        receiver.func_name = 'receiver_%s' % key
        return receiver


def test_meta_connect():
    sentinel = []
    def meta_received(sender, **kw):
        sentinel.append(dict(kw, sender=sender))

    assert not blinker.receiver_connected.receivers
    blinker.receiver_connected.connect(meta_received)
    assert not sentinel

    def receiver(sender, **kw):
        pass
    sig = blinker.Signal()
    sig.connect(receiver)

    assert sentinel == [{'sender': sig,
                         'receiver_arg': receiver,
                         'sender_arg': blinker.ANY,
                         'weak_arg': True}]

    blinker.receiver_connected._clear_state()


def _test_signal_signals(sender):
    sentinel = Sentinel()
    sig = blinker.Signal()

    connected = sentinel.make_receiver('receiver_connected')
    disconnected = sentinel.make_receiver('receiver_disconnected')
    receiver1 = sentinel.make_receiver('receiver1')
    receiver2 = sentinel.make_receiver('receiver2')

    assert not sig.receiver_connected.receivers
    assert not sig.receiver_disconnected.receivers
    sig.receiver_connected.connect(connected)
    sig.receiver_disconnected.connect(disconnected)

    assert sig.receiver_connected.receivers
    assert not sentinel

    for receiver, weak in [(receiver1, True), (receiver2, False)]: