import os
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.files.storage import FileSystemStorage
from django.utils.importlib import import_module

from django.contrib.staticfiles import utils


class StaticFilesStorage(FileSystemStorage):
    """
    Standard file system storage for site media files.
    
    The defaults for ``location`` and ``base_url`` are
    ``STATICFILES_ROOT`` and ``STATICFILES_URL``.
    """
    def __init__(self, location=None, base_url=None, *args, **kwargs):
        if location is None:
            location = settings.STATICFILES_ROOT
        if base_url is None:
            base_url = settings.STATICFILES_URL
        if not location:
            raise ImproperlyConfigured("You're using the staticfiles app "
                "without having set the STATICFILES_ROOT setting. Set it to "
                "the absolute path of the directory that holds static media.")
        if not base_url:
            raise ImproperlyConfigured("You're using the staticfiles app "
                "without having set the STATICFILES_URL setting. Set it to "
                "URL that handles the files served from STATICFILES_ROOT.")
        super(StaticFilesStorage, self).__init__(location, base_url, *args, **kwargs)


class AppStaticStorage(FileSystemStorage):
    """
    A file system storage backend that takes an app module and works
    for the ``static`` directory of it.
    """
    source_dir = 'static'

    def __init__(self, app, *args, **kwargs):
        """
        Returns a static file storage if available in the given app.
        """
        # app is actually the models module of the app. Remove the '.models'.
        bits = app.__name__.split('.')[:-1]
        self.app_name = bits[-1]
        self.app_module = '.'.join(bits)
        # The models module (app) may be a package in which case
        # dirname(app.__file__) would be wrong. Import the actual app
        # as opposed to the models module.
        app = import_module(self.app_module)
        location = self.get_location(os.path.dirname(app.__file__))
        super(AppStaticStorage, self).__init__(location, *args, **kwargs)

    def get_location(self, app_root):
        """
        Given the app root, return the location of the static files of an app,
        by default 'static'. We special case the admin app here since it has
        its static files in 'media'.
        """
        if self.app_module == 'django.contrib.admin':
            return os.path.join(app_root, 'media')
        return os.path.join(app_root, self.source_dir)

    def get_prefix(self):
        """
        Return the path name that should be prepended to files for this app.
        """
        if self.app_module == 'django.contrib.admin':
            return self.app_name
        return None

    def get_files(self, ignore_patterns=[]):
        """
        Return a list containing the relative source paths for all files that
        should be copied for an app.
        """
        files = []
        prefix = self.get_prefix()
        for path in utils.get_files(self, ignore_patterns):
            if prefix:
                path = '/'.join([prefix, path])
            files.append(path)
        return files
