import pytest
from pytest_mock import MockerFixture
from saul_events.publisher import EventPublisher
import attrs
from saul_events.event import Event
from saul_events.event_listener import EventListener
from saul_events.errors.exceptions import InvalidEventTypeError
publisher=EventPublisher()
@attrs.frozen
class ExampleEvent(Event):
    data: dict


def test_should_add_method_to_subscribers():
    def handle_example_event(event:ExampleEvent):
        return "Handle example event"
    listener=EventListener(None,handle_example_event)
    publisher.subscribe(ExampleEvent,listener)
    
    assert publisher._EventPublisher__listeners[ExampleEvent][0]==listener
    
    publisher.unsubscribe(ExampleEvent,handle_example_event)
    
def test_should_raise_EventTypeError():
    class InvalidEvent():
        pass
    
    def handler(ev:InvalidEvent):
        pass
    
    with pytest.raises(InvalidEventTypeError):
        publisher.subscribe(InvalidEvent,EventListener(None,handler))
    
def test_should_react_to_event():
    init_value=0
    def react_to_example_event(ev:ExampleEvent):
        nonlocal init_value 
        init_value+=2
        
    event=ExampleEvent({})
    publisher.subscribe(ExampleEvent,EventListener(None,react_to_example_event))
    publisher.publish(event)
    
    assert init_value==2
    
    publisher.unsubscribe_all()
    
        
