import os
import sys
import shutil
from optparse import make_option

from django.conf import settings
from django.core.files.storage import get_storage_class
from django.core.management.base import CommandError, NoArgsCommand

from django.contrib.staticfiles import finders

class Command(NoArgsCommand):
    """
    Command that allows to copy or symlink media files from different
    locations to the settings.STATIC_ROOT.
    """
    option_list = NoArgsCommand.option_list + (
        make_option('--noinput', action='store_false', dest='interactive',
            default=True, help="Do NOT prompt the user for input of any "
                "kind."),
        make_option('-i', '--ignore', action='append', default=[],
            dest='ignore_patterns', metavar='PATTERN',
            help="Ignore files or directories matching this glob-style "
                "pattern. Use multiple times to ignore more."),
        make_option('-n', '--dry-run', action='store_true', dest='dry_run',
            default=False, help="Do everything except modify the filesystem."),
        make_option('-l', '--link', action='store_true', dest='link',
            default=False, help="Create a symbolic link to each file instead of copying."),
        make_option('--no-default-ignore', action='store_false',
            dest='use_default_ignore_patterns', default=True,
            help="Don't ignore the common private glob-style patterns 'CVS', "
                "'.*' and '*~'."),
    )
    help = "Collect static files from apps and other locations in a single location."

    def handle_noargs(self, **options):
        symlink = options['link']
        ignore_patterns = options['ignore_patterns']
        if options['use_default_ignore_patterns']:
            ignore_patterns += ['CVS', '.*', '*~']
        ignore_patterns = list(set(ignore_patterns))
        self.copied_files = set()
        self.symlinked_files = set()
        self.unmodified_files = set()
        self.destination_storage = get_storage_class(settings.STATICFILES_STORAGE)()

        try:
            self.destination_storage.path('')
        except NotImplementedError:
            self.destination_local = False
        else:
            self.destination_local = True

        if symlink:
            if sys.platform == 'win32':
                raise CommandError("Symlinking is not supported by this "
                                   "platform (%s)." % sys.platform)
            if not self.destination_local:
                raise CommandError("Can't symlink to a remote destination.")

        # Warn before doing anything more.
        if options.get('interactive'):
            confirm = raw_input("""
You have requested to collate static files and collect them at the destination
location as specified in your settings file.

This will overwrite existing files.
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: """)
            if confirm != 'yes':
                raise CommandError("Static files build cancelled.")

        # Use ints for file times (ticket #14665)
        os.stat_float_times(False)

        for finder in finders.get_finders():
            for source, prefix, storage in finder.list(ignore_patterns):
                self.copy_file(source, prefix, storage, **options)

        verbosity = int(options.get('verbosity', 1))
        actual_count = len(self.copied_files) + len(self.symlinked_files)
        unmodified_count = len(self.unmodified_files)
        if verbosity >= 1:
            self.stdout.write("\n%s static file%s %s to '%s'%s.\n"
                              % (actual_count, actual_count != 1 and 's' or '',
                                 symlink and 'symlinked' or 'copied',
                                 settings.STATIC_ROOT,
                                 unmodified_count and ' (%s unmodified)'
                                 % unmodified_count or ''))

    def copy_file(self, source, prefix, source_storage, **options):
        """
        Attempt to copy (or symlink) ``source`` to ``destination``,
        returning True if successful.
        """
        source_path = source_storage.path(source)
        try:
            source_last_modified = source_storage.modified_time(source)
        except (OSError, NotImplementedError):
            source_last_modified = None
        if prefix:
            destination = '/'.join([prefix, source])
        else:
            destination = source
        symlink = options['link']
        dry_run = options['dry_run']
        verbosity = int(options.get('verbosity', 1))

        if destination in self.copied_files:
            if verbosity >= 2:
                self.stdout.write("Skipping '%s' (already copied earlier)\n"
                                  % destination)
            return False

        if destination in self.symlinked_files:
            if verbosity >= 2:
                self.stdout.write("Skipping '%s' (already linked earlier)\n"
                                  % destination)
            return False

        if self.destination_storage.exists(destination):
            try:
                destination_last_modified = \
                    self.destination_storage.modified_time(destination)
            except (OSError, NotImplementedError):
                # storage doesn't support ``modified_time`` or failed.
                pass
            else:
                destination_is_link = os.path.islink(
                    self.destination_storage.path(destination))
                if destination_last_modified >= source_last_modified:
                    if (not symlink and not destination_is_link):
                        if verbosity >= 2:
                            self.stdout.write("Skipping '%s' (not modified)\n"
                                              % destination)
                        self.unmodified_files.add(destination)
                        return False
            if dry_run:
                if verbosity >= 2:
                    self.stdout.write("Pretending to delete '%s'\n"
                                      % destination)
            else:
                if verbosity >= 2:
                    self.stdout.write("Deleting '%s'\n" % destination)
                self.destination_storage.delete(destination)

        if symlink:
            destination_path = self.destination_storage.path(destination)
            if dry_run:
                if verbosity >= 1:
                    self.stdout.write("Pretending to symlink '%s' to '%s'\n"
                                      % (source_path, destination_path))
            else:
                if verbosity >= 1:
                    self.stdout.write("Symlinking '%s' to '%s'\n"
                                      % (source_path, destination_path))
                try:
                    os.makedirs(os.path.dirname(destination_path))
                except OSError:
                    pass
                os.symlink(source_path, destination_path)
            self.symlinked_files.add(destination)
        else:
            if dry_run:
                if verbosity >= 1:
                    self.stdout.write("Pretending to copy '%s' to '%s'\n"
                                      % (source_path, destination))
            else:
                if self.destination_local:
                    destination_path = self.destination_storage.path(destination)
                    try:
                        os.makedirs(os.path.dirname(destination_path))
                    except OSError:
                        pass
                    shutil.copy2(source_path, destination_path)
                    if verbosity >= 1:
                        self.stdout.write("Copying '%s' to '%s'\n"
                                          % (source_path, destination_path))
                else:
                    source_file = source_storage.open(source)
                    self.destination_storage.save(destination, source_file)
                    if verbosity >= 1:
                        self.stdout.write("Copying %s to %s\n"
                                          % (source_path, destination))
            self.copied_files.add(destination)
        return True
