# -*- coding: utf-8 -*-
import threading


class DEvent:
    def __init__(self):
        self.listeners = {}
        self.lock = threading.Lock()

    def on(self, eventName, callback):
        with self.lock:
            if callback is None or not callable(callback):
                return
            if eventName not in self.listeners:
                self.listeners[eventName] = [callback]
            elif callback not in self.listeners[eventName]:
                self.listeners[eventName].append(callback)
            else:
                print(f"Callback '{callback}' is already subscribed to event \
'{eventName}'")

    def off(self, eventName, callback):
        with self.lock:
            if eventName not in self.listeners:
                print(f"No subscribers found for event '{eventName}'")
                return
            if callback in self.listeners[eventName]:
                self.listeners[eventName].remove(callback)
            else:
                print(f"Callback '{callback}' is not subscribed to event \
'{eventName}'")

    def emit(self, eventName, *args, **kwargs):
        with self.lock:
            if eventName in self.listeners:
                for callback in self.listeners[eventName]:
                    try:
                        if callback is None or not callable(callback):
                            continue
                        callback(*args, **kwargs)
                    except Exception as e:
                        print(f"An error occurred while executing callback \
for event '{eventName}': {e}")
            else:
                print(f"No subscribers found for event '{eventName}'")
