# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.

from twisted.trial import unittest
from elisa.core.tests.elisa_test_case import ElisaTestCase
from elisa.core import log

from elisa.base_components.message import Message

from elisa.core.bus import bus
from twisted.internet import defer, reactor
import platform

class DataMessage(Message):
    def __init__(self, data):
        Message.__init__(self)
        self.data = data

class FooMessage(Message):
    def __init__(self, foo):
        Message.__init__(self)
        self.foo = foo


class TestMessageBus(ElisaTestCase):
    
    def __init__(self, methodName='runTest'):
        ElisaTestCase.__init__(self, methodName)
        if platform.system() == 'Windows':
            self.skip = "test not supported under windows (Twisted lock)"

    def setUp(self):
        ElisaTestCase.setUp(self)
        self._bus = bus.Bus()
        self._bus.start()

    def tearDown(self):
        ElisaTestCase.setUp(self)
        self._bus.stop()

    def test_delayed_dispatch(self):
        global received_messages
        received_messages = []
        mybus = bus.Bus()

        def on_message(message, sender):
            global received_messages
            received_messages.append(message)

        mybus.register(on_message)

        for i in range(5):
            data = '%s. Hello you' % i
            mybus.send_message(DataMessage(data), sender=self)

        def done():
            global received_messages
            self.assertEqual(len(received_messages), 5)
            mybus.unregister(on_message)
            mybus.stop()
            
        mybus.start()
        reactor.callFromThread(done)
        
    def test_simple_emit(self):
        """ Check a message receiver callback correctly gets called on
        message bus dispatch.
        """
        global received_messages
        received_messages = []

        def on_message(message, sender):
            global received_messages
            received_messages.append(message)

        self._bus.register(on_message)

        for i in range(5):
            self._bus.send_message(DataMessage("data"), sender=self)
            
        def done():
            global received_messages
            self.assertEqual(len(received_messages), 5)
                        
        reactor.callFromThread(done)
        
    def test_message_filter(self):
        """
        """
        global received_messages
        received_messages = []

        def on_message(message, sender):
            global received_messages
            received_messages.append(message)

        self._bus.register(on_message, FooMessage)

        for i in range(5):
            data = '%s. Hello you' % i
            self._bus.send_message(DataMessage(data), sender=self)

        global sent_foo_messages
        sent_foo_messages = []
        for i in range(5):
            data = '%s. Hello you' % i
            msg = FooMessage(data)
            self._bus.send_message(msg, sender=self)
            sent_foo_messages.append(msg)

        def done():
            global received_messages
            global sent_foo_messages
            self.assertEqual(len(received_messages), 5)
            for msg in received_messages:
                self.failIf(msg not in sent_foo_messages)
            self._bus.unregister(on_message)

        reactor.callFromThread(done)

    def test_multiple_filters(self):
        """
        """
        global received_messages
        received_messages = []

        def on_message(message, sender):
            global received_messages
            received_messages.append(message)

        self._bus.register(on_message, DataMessage,FooMessage)

        global sent_messages
        sent_messages = []
        for i in range(5):
            data = '%s. Hello you' % i
            msg = DataMessage(data)
            self._bus.send_message(msg, sender=self)
            sent_messages.append(msg)

        for i in range(5):
            data = '%s. Hello you' % i
            msg = FooMessage(data)
            self._bus.send_message(msg, sender=self)
            sent_messages.append(msg)

        def done():
            global received_messages
            global sent_messages
            self.assertEqual(len(received_messages), 10)
            for msg in received_messages:
                self.failIf(msg not in sent_messages)

        reactor.callFromThread(done)

    def test_decorator(self):
        """
        """
        global received_messages
        received_messages = []

        @bus.bus_listener(self._bus, FooMessage)
        def on_message(message, sender):
            global received_messages
            received_messages.append(message)

        for i in range(5):
            data = '%s. Hello you' % i
            self._bus.send_message(DataMessage(data), sender=self)

        global sent_foo_messages 
        sent_foo_messages = []
        for i in range(5):
            data = '%s. Hello you' % i
            msg = FooMessage(data)
            self._bus.send_message(msg, sender=self)
            sent_foo_messages.append(msg)

        def done():
            global received_messages
            global sent_foo_messages 
            self.assertEqual(len(received_messages), 5)
            for msg in received_messages:
                self.failIf(msg not in sent_foo_messages)
            self._bus.unregister(on_message)

        reactor.callFromThread(done)
