from typing import Optional, Type, Sequence


class AbstractHandler(object):
    HANDLER_KEY: str = None


class HandlerClassRegistry(object):
    def __init__(self, handlers: Sequence[Type[AbstractHandler]] = ()):
        self._handler_map = dict()
        self.get_handler_cls = self._handler_map.get
        for cls in handlers:
            self.add_handler(cls)

    def add_handler(self, cls: Type[AbstractHandler]):
        key = self._key_from_handler_cls(cls)
        if key in self._handler_map:
            raise Exception("Handler key conflict: %s" % (str(cls.HANDLER_KEY),))
        self._handler_map[key] = cls

    def _key_from_handler_cls(self, cls: Type[AbstractHandler]) -> str:
        if cls.HANDLER_KEY:
            if not isinstance(cls.HANDLER_KEY, str):
                raise Exception("Invalid handler key")
            return cls.HANDLER_KEY
        else:
            raise Exception("Incomplete handler implementation")

    def get_handler(self, key: str, *args, **kwargs) -> Optional[AbstractHandler]:
        handler_cls = self._handler_map.get(key)
        if handler_cls:
            return handler_cls(*args, **kwargs)
