from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.dispatch import Signal

from djangochannelsrestframework.observer.base_observer import BaseObserver


class Observer(BaseObserver):
    def __init__(self, func, signal: Signal = None, kwargs=None):
        super().__init__(func)
        if kwargs is None:
            kwargs = {}
        self.signal = signal
        self.signal_kwargs = kwargs
        self._serializer = None
        self.signal.connect(self.handle, **self.signal_kwargs)

    def handle(self, signal, *args, **kwargs):
        message = self.serialize(signal, *args, **kwargs)
        channel_layer = get_channel_layer()
        for group_name in self.group_names_for_signal(*args, message=message, **kwargs):
            async_to_sync(channel_layer.group_send)(group_name, message)

    def group_names(self, *args, **kwargs):
        yield "{}-{}-signal-{}".format(
            self._uuid,
            self.func.__name__.replace("_", "."),
            ".".join(
                arg.lower().replace("_", ".") for arg in self.signal.providing_args
            ),
        )