import glob
import io
import os
import sys

from django.conf import settings
from django.core.management import CommandError
from django.core.management.commands.makemessages import Command as MakeMessagesCommand, check_programs

from judge.models import NavigationBar, ProblemType


class Command(MakeMessagesCommand):
    def add_arguments(self, parser):
        parser.add_argument('--locale', '-l', default=[], dest='locale', action='append',
                            help='Creates or updates the message files for the given locale(s) (e.g. pt_BR). '
                                 'Can be used multiple times.')
        parser.add_argument('--exclude', '-x', default=[], dest='exclude', action='append',
                            help='Locales to exclude. Default is none. Can be used multiple times.')
        parser.add_argument('--all', '-a', action='store_true', dest='all',
                            default=False, help='Updates the message files for all existing locales.')
        parser.add_argument('--no-wrap', action='store_true', dest='no_wrap',
                            default=False, help="Don't break long message lines into several lines.")
        parser.add_argument('--no-obsolete', action='store_true', dest='no_obsolete',
                            default=False, help="Remove obsolete message strings.")
        parser.add_argument('--keep-pot', action='store_true', dest='keep_pot',
                            default=False, help="Keep .pot file after making messages. Useful when debugging.")

    def handle(self, *args, **options):
        locale = options.get('locale')
        exclude = options.get('exclude')
        self.domain = 'dmoj-user'
        self.verbosity = options.get('verbosity')
        process_all = options.get('all')

        # Need to ensure that the i18n framework is enabled
        if settings.configured:
            settings.USE_I18N = True
        else:
            settings.configure(USE_I18N=True)

        # Avoid messing with mutable class variables
        if options.get('no_wrap'):
            self.msgmerge_options = self.msgmerge_options[:] + ['--no-wrap']
            self.msguniq_options = self.msguniq_options[:] + ['--no-wrap']
            self.msgattrib_options = self.msgattrib_options[:] + ['--no-wrap']
            self.xgettext_options = self.xgettext_options[:] + ['--no-wrap']
        if options.get('no_location'):
            self.msgmerge_options = self.msgmerge_options[:] + ['--no-location']
            self.msguniq_options = self.msguniq_options[:] + ['--no-location']
            self.msgattrib_options = self.msgattrib_options[:] + ['--no-location']
            self.xgettext_options = self.xgettext_options[:] + ['--no-location']

        self.no_obsolete = options.get('no_obsolete')
        self.keep_pot = options.get('keep_pot')

        if locale is None and not exclude and not process_all:
            raise CommandError("Type '%s help %s' for usage information." % (
                os.path.basename(sys.argv[0]), sys.argv[1]))

        self.invoked_for_django = False
        self.locale_paths = []
        self.default_locale_path = None
        if os.path.isdir(os.path.join('conf', 'locale')):
            self.locale_paths = [os.path.abspath(os.path.join('conf', 'locale'))]
            self.default_locale_path = self.locale_paths[0]
            self.invoked_for_django = True
        else:
            self.locale_paths.extend(settings.LOCALE_PATHS)
            # Allow to run makemessages inside an app dir
            if os.path.isdir('locale'):
                self.locale_paths.append(os.path.abspath('locale'))
            if self.locale_paths:
                self.default_locale_path = self.locale_paths[0]
                if not os.path.exists(self.default_locale_path):
                    os.makedirs(self.default_locale_path)

        # Build locale list
        locale_dirs = list(filter(os.path.isdir, glob.glob('%s/*' % self.default_locale_path)))
        all_locales = list(map(os.path.basename, locale_dirs))

        # Account for excluded locales
        if process_all:
            locales = all_locales
        else:
            locales = locale or all_locales
            locales = set(locales) - set(exclude)

        if locales:
            check_programs('msguniq', 'msgmerge', 'msgattrib')

        check_programs('xgettext')

        try:
            potfiles = self.build_potfiles()

            # Build po files for each selected locale
            for locale in locales:
                if self.verbosity > 0:
                    self.stdout.write("processing locale %s\n" % locale)
                for potfile in potfiles:
                    self.write_po_file(potfile, locale)
        finally:
            if not self.keep_pot:
                self.remove_potfiles()

    def find_files(self, root):
        return []

    def _emit_message(self, potfile, string):
        potfile.write('''
msgid "%s"
msgstr ""
''' % string.replace('\\', r'\\').replace('\t', '\\t').replace('\n', '\\n').replace('"', '\\"'))

    def process_files(self, file_list):
        with io.open(os.path.join(self.default_locale_path, 'dmoj-user.pot'), 'w', encoding='utf-8') as potfile:
            if self.verbosity > 1:
                self.stdout.write('processing navigation bar')
            for label in NavigationBar.objects.values_list('label', flat=True):
                if self.verbosity > 2:
                    self.stdout.write('processing navigation item label "%s"\n' % label)
                self._emit_message(potfile, label)

            if self.verbosity > 1:
                self.stdout.write('processing problem types')
            for name in ProblemType.objects.values_list('full_name', flat=True):
                if self.verbosity > 2:
                    self.stdout.write('processing problem type name "%s"\n' % name)
                self._emit_message(potfile, name)