# -*- coding: utf-8 -*-
import inspect
from django.utils import six
from django.contrib import admin
from django.core.exceptions import ImproperlyConfigured
from muser.utils import get_object


class ExtensionsMixin(object):
    """Extension mixin class to include all content type extension. """
    @classmethod
    def register_extensions(cls, *extensions):
        """
        Register all extensions passed as arguments.

        Extensions should be specified as a string to the python module
        containing the extension.
        """
        if not hasattr(cls, '_extensions'):
            cls._extensions = []
            cls._extensions_seen = []

        for ext in extensions:
            if ext in cls._extensions:
                continue

            extension = None

            # check if ext is a Class
            if inspect.isclass(ext) and issubclass(ext, Extension):
                extension = ext

            elif isinstance(ext, six.string_types):
                try:
                    extension = get_object(ext)
                except (AttributeError, ImportError, ValueError):
                    if not extension:
                        raise ImproperlyConfigured(
                            '%s is not a valid extension for %s' % (
                                ext, cls.__name__))

            if hasattr(extension, 'Extension'):
                extension = extension.Extension

            elif hasattr(extension, 'register'):
                extension = extension.register

            elif hasattr(extension, '__call__'):
                pass

            else:
                raise ImproperlyConfigured(
                    '%s is not a valid extension for %s' % (
                        ext, cls.__name__))

            if extension in cls._extensions_seen:
                continue
            cls._extensions_seen.append(extension)

            if hasattr(extension, 'handle_model'):
                cls._extensions.append(extension(cls))
            else:
                raise ImproperlyConfigured(
                    '%r is an invalid extension.' % extension)


class Extension(object):
    """Handle a extension object for content type. """
    def __init__(self, model, **kwargs):
        self.model = model
        for key, value in kwargs.items():
            if not hasattr(self, key):
                raise TypeError('%s() received an invalid keyword %r' % (
                    self.__class__.__name__, key))
            setattr(self, key, value)

        self.handle_model()

    def handle_model(self):
        raise NotImplementedError

    def handle_modeladmin(self, modeladmin):
        pass


class ExtensionModelAdmin(admin.ModelAdmin):
    def __init__(self, *args, **kwargs):
        super(ExtensionModelAdmin, self).__init__(*args, **kwargs)
        self.initialize_extensions()

    def initialize_extensions(self):
        if not hasattr(self, '_extensions_initialized'):
            self._extensions_initialized = True
            for extension in getattr(self.model, '_extensions', []):
                extension.handle_modeladmin(self)

    def add_extension_options(self, *f):
        if self.fieldsets is None:
            return

        if isinstance(f[-1], dict):     # called with a fieldset
            self.fieldsets.insert(self.fieldset_insertion_index, f)
            f[1]['classes'] = list(f[1].get('classes', []))
            f[1]['classes'].append('collapse')
        elif f:   # assume called with "other" fields
            try:
                self.fieldsets[1][1]['fields'].extend(f)
            except IndexError:
                # Fall back to first fieldset if second does not exist
                # XXX This is really messy.
                self.fieldsets[0][1]['fields'].extend(f)
