import os

from django.utils.translation import ugettext_lazy as _

from . import settings

from orchestra.apps.orchestration import ServiceController


class Bind9MasterDomainBackend(ServiceController):
    verbose_name = _("Bind9 master domain")
    model = 'domains.Domain'
    related_models = (
        ('domains.Record', 'domain__origin'),
        ('domains.Domain', 'origin'),
    )
    
    @classmethod
    def is_main(cls, obj):
        """ work around Domain.top self relationship """
        if super(Bind9MasterDomainBackend, cls).is_main(obj):
            return not obj.top
    
    def save(self, domain):
        context = self.get_context(domain)
        domain.refresh_serial()
        context['zone'] = ';; %(banner)s\n' % context
        context['zone'] += domain.render_zone()
        self.append("{ echo -e '%(zone)s' | diff -N -I'^;;' %(zone_path)s - ; } ||"
                    "   { echo -e '%(zone)s' > %(zone_path)s; UPDATED=1; }" % context)
        self.update_conf(context)
    
    def update_conf(self, context):
        self.append("grep '\s*zone\s*\"%(name)s\"\s*{' %(conf_path)s > /dev/null ||"
                    "   { echo -e '%(conf)s' >> %(conf_path)s; UPDATED=1; }" % context)
        for subdomain in context['subdomains']:
            context['name'] = subdomain.name
            self.delete_conf(context)
    
    def delete(self, domain):
        context = self.get_context(domain)
        self.append('rm -f %(zone_path)s;' % context)
        self.delete_conf(context)
    
    def delete_conf(self, context):
        self.append('awk -v s=%(name)s \'BEGIN {'
                    '  RS=""; s="zone \\""s"\\""'
                    '} $0!~s{ print $0"\\n" }\' %(conf_path)s > %(conf_path)s.tmp'
                    % context)
        self.append('diff -I"^\s*//" %(conf_path)s.tmp %(conf_path)s || UPDATED=1' % context)
        self.append('mv %(conf_path)s.tmp %(conf_path)s' % context)
    
    def commit(self):
        """ reload bind if needed """
        self.append('[[ $UPDATED == 1 ]] && service bind9 reload')
    
    def get_context(self, domain):
        context = {
            'name': domain.name,
            'zone_path': settings.DOMAINS_ZONE_PATH % {'name': domain.name},
            'subdomains': domain.get_subdomains(),
            'banner': self.get_banner(),
        }
        context.update({
            'conf_path': settings.DOMAINS_MASTERS_PATH,
            'conf': 'zone "%(name)s" {\n'
                    '    // %(banner)s\n'
                    '    type master;\n'
                    '    file "%(zone_path)s";\n'
                    '};\n' % context
        })
        return context


class Bind9SlaveDomainBackend(Bind9MasterDomainBackend):
    verbose_name = _("Bind9 slave domain")
    related_models = (('domains.Domain', 'origin'),)
    
    def save(self, domain):
        context = self.get_context(domain)
        self.update_conf(context)
    
    def delete(self, domain):
        context = self.get_context(domain)
        self.delete_conf(context)

    def commit(self):
        """ ideally slave should be restarted after master """
        self.append('[[ $UPDATED == 1 ]] && { sleep 1 && service bind9 reload; } &')
    
    def get_context(self, domain):
        context = {
            'name': domain.name,
            'masters': '; '.join(settings.DOMAINS_MASTERS),
            'subdomains': domain.get_subdomains()
        }
        context.update({
            'conf_path': settings.DOMAINS_SLAVES_PATH,
            'conf': 'zone "%(name)s" {\n'
                    '    type slave;\n'
                    '    file "%(name)s";\n'
                    '    masters { %(masters)s; };\n'
                    '};\n' % context
        })
        return context