# coding=utf-8
"""
A utilities of permission handler
"""
from __future__ import unicode_literals
import inspect
from django.core.exceptions import ImproperlyConfigured
from permission.conf import settings
from permission.compat import isstr
from permission.compat import import_string


class PermissionHandlerRegistry(object):
    """
    A registry class of permission handler
    """
    def __init__(self):
        self._registry = {}

    def register(self, model, handler=None):
        """
        Register a permission handler to the model

        Parameters
        ----------
        model : django model class
            A django model class
        handler : permission handler class, string, or None
            A permission handler class or a dotted path

        Raises
        ------
        ImproperlyConfigured
            Raise when the model is abstract model
        KeyError
            Raise when the model is already registered in registry
            The model cannot have more than one handler.
        """
        from permission.handlers import PermissionHandler
        if model._meta.abstract:
            raise ImproperlyConfigured(
                    'The model %s is abstract, so it cannot be registered '
                    'with permission.' % model)
        if model in self._registry:
            raise KeyError("A permission handler class is already "
                            "registered for '%s'" % model)
        if handler is None:
            handler = settings.PERMISSION_DEFAULT_PERMISSION_HANDLER
        if isstr(handler):
            handler = import_string(handler)
        if not inspect.isclass(handler):
            raise AttributeError(
                    "`handler` attribute must be a class. "
                    "An instance was specified.")
        if not issubclass(handler, PermissionHandler):
            raise AttributeError(
                    "`handler` attribute must be a subclass of "
                    "`permission.handlers.PermissionHandler`")

        # Instantiate the handler to save in the registry
        instance = handler(model)
        self._registry[model] = instance

    def unregister(self, model):
        """
        Unregister a permission handler from the model

        Parameters
        ----------
        model : django model class
            A django model class

        Raises
        ------
        KeyError
            Raise when the model have not registered in registry yet.
        """
        if model not in self._registry:
            raise KeyError("A permission handler class have not been "
                           "registered for '%s' yet" % model)
        # remove from registry
        del self._registry[model]

    def get_handlers(self):
        """
        Get registered handler instances

        Returns
        -------
        tuple
            permission handler tuple
        """
        return tuple(self._registry.values())

registry = PermissionHandlerRegistry()
"""Permission handler registry instance"""
