import os
from optparse import make_option
from shutil import copyfile

from django.core.management.base import BaseCommand, CommandError
from django.utils.importlib import import_module

class Command(BaseCommand):
    help = "List all templates."
    args = "[appname [appname2 [...]]]"

    option_list = BaseCommand.option_list + (
         make_option('-e', '--exclude', dest='exclude',action='append', default=[],
            help='App to exclude (use multiple --exclude to exclude multiple apps).'),
         make_option('-c', '--copy-to', dest='copy_to',action='store', 
                     default=False, help=('Copy templates to direcdory. (files '
                                          'are not oweritten if they exist).')),

    )

    def handle(self, *app_labels, **options):
        exclude = options.get('exclude',[])
        copy_to = options.get('copy_to', False)

        apps = self._get_apps(app_labels, exclude)

        templates_dirs = []

        for app in apps:
            module = import_module(app)
            module_dir = os.path.dirname(module.__file__)
            templates_dirs.append(os.path.join(module_dir, 'templates'))

        for templates_dir in templates_dirs:
            templates = self._find_files(templates_dir)

            print templates_dir, ':'

            for template_name in templates:
                print '    ', template_name

                if copy_to:
                    copied = self._copy_file(templates_dir, copy_to, template_name)
                    if copied:
                        print "        Copied."
                    else:
                        print "        Template already exists."

    def _get_apps(self, app_labels, exclude):
        from django.conf import settings

        apps = dict([(app.split('.')[-1], app) for app in settings.INSTALLED_APPS])

        try:
            [apps.pop(app_label) for app_label in exclude]
        except KeyError, key:
            raise CommandError("Unknown application: %s in excluded apps" % key)

        if len(app_labels) > 0:
            try:
                apps = [apps.pop(app_label) for app_label in app_labels]
            except KeyError, key:
                raise CommandError("Unknown application: %s" % key)
        else:
            apps = apps.values()

        return apps

    def _find_files(self, location):
        """Recursively finds files at location. Returns list of relative to
        filename files"""
        files = []
        for dirpath, dirnames, filenames in os.walk(location):
            for filename in filenames:
                file_name = os.path.join(dirpath, filename) \
                                   .replace(location, '') \
                                   .strip('/\\')
                files.append(file_name)
        return files

    def _copy_file(self, src, dest, file):
        src = os.path.join(src, file)
        dest = os.path.join(dest, file)
        dest_dir = os.path.dirname(dest)

        if not os.path.exists(dest_dir):
            os.makedirs(dest_dir, 0773)

        if not os.path.exists(dest):
            copyfile(src, dest)
            return True
        else:
            return False