import warnings
from django.conf import settings as django_settings
from django.core.exceptions import ImproperlyConfigured
from django.test.signals import setting_changed
from django.utils import six
from django.utils.functional import LazyObject
from django.utils.module_loading import import_string


ACCOUNTS_SETTINGS_NAMESPACE = 'ACCOUNTS'


class ObjDict(dict):
    def __getattribute__(self, item):
        try:
            if isinstance(self[item], str):
                self[item] = import_string(self[item])
            value = self[item]
        except KeyError:
            value = super(ObjDict, self).__getattribute__(item)

        return value


default_settings = {
    'SEND_ACTIVATION_EMAIL': True,
    'ACTIVATION_URL': 'accounts/activate/{uid}/{token}',
    'PASSWORD_RESET_URL': 'accounts/password-reset/{uid}/{token}',
    'SERIALIZERS': ObjDict({
        'password_reset':
            'accounts.serializers.ResetPasswordSerializer',
        'password_reset_confirm':
            'accounts.serializers.ResetPasswordConfirmSerializer',
        'password_change':
            'accounts.serializers.PasswordChangeSerializer',
        'user_create':
            'accounts.serializers.UserCreateSerializer',
        'username_change':
            'accounts.serializers.ChangeUserNameSerializer',
        'user':
            'accounts.serializers.UserSerializer',
    }),
    'EMAIL': ObjDict({
        'activation': 'accounts.utils.ActivationEmail',
        'password_reset': 'accounts.utils.PasswordResetEmail',
    }),
    'MESSAGE': ObjDict({
        'password_reset':{"message":"password reset link sent"},
        'password_reset_confirm': {"message":"password reset sucessfully"},
        'password_change': {"message":"password change sucessfully"},
        'activation': {"message":"user activated sucessfully"},
        'activation_fail':{'message':'fail,this code is already used'},
        'username_change':{'message':'username change sucessfully'},
    }),
    'USER_EMAIL_FIELD_NAME': 'email',
}



class Settings(object):
    def __init__(self, default_settings, explicit_overriden_settings=None):
        if explicit_overriden_settings is None:
            explicit_overriden_settings = {}

        overriden_settings = getattr(
            django_settings, ACCOUNTS_SETTINGS_NAMESPACE, {}
        ) or explicit_overriden_settings

        self._load_default_settings()
        self._override_settings(overriden_settings)

    def _load_default_settings(self):
        for setting_name, setting_value in six.iteritems(default_settings):
            if setting_name.isupper():
                setattr(self, setting_name, setting_value)

    def _override_settings(self, overriden_settings):
        for setting_name, setting_value in six.iteritems(overriden_settings):
            value = setting_value
            if isinstance(setting_value, dict):
                value = getattr(self, setting_name, {})
                value.update(ObjDict(setting_value))
            setattr(self, setting_name, value)


class LazySettings(LazyObject):
    def _setup(self, explicit_overriden_settings=None):
        self._wrapped = Settings(default_settings, explicit_overriden_settings)

    def get(self, key):
        """
        This function is here only to provide backwards compatibility in
        case anyone uses old settings interface.
        It is strongly encouraged to use dot notation.
        """
        warnings.warn(
            'The settings.get(key) is superseded by the dot attribute access.',
            PendingDeprecationWarning
        )
        try:
            return getattr(self, key)
        except AttributeError:
            raise ImproperlyConfigured('Missing settings: {}[\'{}\']'.format(
                ACCOUNTS_SETTINGS_NAMESPACE, key)
            )


settings = LazySettings()


def reload_accounts_settings(*args, **kwargs):
    global settings
    setting, value = kwargs['setting'], kwargs['value']
    if setting == ACCOUNTS_SETTINGS_NAMESPACE:
        settings._setup(explicit_overriden_settings=value)


setting_changed.connect(reload_accounts_settings)
