import os

from django.conf import settings
from django.core.management import setup_environ

from celery.loaders.default import Loader as DefaultLoader
from celery.loaders.djangoapp import Loader as DjangoLoader

"""
.. class:: Loader

The current loader class.

"""
Loader = DefaultLoader
if settings.configured:
    Loader = DjangoLoader
else:
    try:
        # A settings module may be defined, but Django didn't attempt to
        # load it yet. As an alternative to calling the private _setup(),
        # we could also check whether DJANGO_SETTINGS_MODULE is set.
        settings._setup()
    except ImportError:
        if not callable(getattr(os, "fork", None)):
            # Platform doesn't support fork()
            # XXX On systems without fork, multiprocessing seems to be
            # launching the processes in some other way which does
            # not copy the memory of the parent process. This means that any
            # configured env might be lost. This is a hack to make it work
            # on Windows.
            # A better way might be to use os.environ to set the currently
            # used configuration method so to propogate it to the "child"
            # processes. But this has to be experimented with.
            # [asksol/heyman]
            try:
                settings_mod = os.environ.get("DJANGO_SETTINGS_MODULE",
                                              "settings")
                project_settings = __import__(settings_mod, {}, {}, [''])
                setup_environ(project_settings)
                Loader = DjangoLoader
            except ImportError:
                pass
    else:
        Loader = DjangoLoader

"""
.. data:: current_loader

The current loader instance.

"""
current_loader = Loader()


"""
.. data:: settings

The global settings object.

"""
settings = current_loader.conf

import os
import importlib

from django.conf import settings
from django.core.management import setup_environ

from carrot.utils import rpartition
from celery.loaders.default import Loader as DefaultLoader
from celery.loaders.djangoapp import Loader as DjangoLoader

LOADER_ALIASES = {"django": "celery.loaders.djangoapp",
                  "default": "celery.loaders.default"}
LOADER_CLASS_NAME = "Loader"
_loader_cache = {}


def resolve_loader(loader):
    return LOADER_ALIASES.get(loader, loader)


def _get_loader_cls(loader):
    loader = resolve_loader(loader)
    loader_module = importlib.import_module(loader)
    return getattr(loader_module, LOADER_CLASS_NAME)


def get_loader_cls(loader):
    """Get loader class by name/alias"""
    if loader not in _loader_cache:
        _loader_cache[loader] = _get_loader_cls(loader)
    return _loader_cache[loader]


def _detect_loader():
    loader = os.environ.get("CELERY_LOADER")
    if loader:
        return get_loader_cls(loader)

    if settings.configured:
        return DjangoLoader
    try:
        # A settings module may be defined, but Django didn't attempt to
        # load it yet. As an alternative to calling the private _setup(),
        # we could also check whether DJANGO_SETTINGS_MODULE is set.
        settings._setup()
    except ImportError:
        if not callable(getattr(os, "fork", None)):
            # Platform doesn't support fork()
            # XXX On systems without fork, multiprocessing seems to be
            # launching the processes in some other way which does
            # not copy the memory of the parent process. This means
            # any configured env might be lost. This is a hack to make
            # it work on Windows.
            # A better way might be to use os.environ to set the currently
            # used configuration method so to propogate it to the "child"
            # processes. But this has to be experimented with.
            # [asksol/heyman]
            try:
                settings_mod = os.environ.get("DJANGO_SETTINGS_MODULE",
                                                "settings")
                project_settings = __import__(settings_mod, {}, {}, [''])
                setup_environ(project_settings)
                return DjangoLoader
            except ImportError:
                pass
    else:
        return DjangoLoader

    return DefaultLoader

"""
.. class:: Loader

The current loader class.

"""
Loader = _detect_loader()

"""
.. data:: current_loader

The current loader instance.

"""
current_loader = Loader()


"""
.. data:: settings

The global settings object.

"""
settings = current_loader.conf

Support setting custom loader with the CELERY_LOADER environment variable.