import os

from optparse import make_option

from django.core.management.base import BaseCommand

from orchestra.utils.system import run, check_root

class Command(BaseCommand):
    def __init__(self, *args, **kwargs):
        super(Command, self).__init__(*args, **kwargs)
        self.option_list = BaseCommand.option_list + (
            make_option('--db_name', dest='db_name', default='orchestra',
                help='Specifies the database to create.'),
            make_option('--db_user', dest='db_user', default='orchestra',
                help='Specifies the database to create.'),
            make_option('--db_password', dest='db_password', default='orchestra',
                help='Specifies the database to create.'),
            make_option('--db_host', dest='db_host', default='localhost',
                help='Specifies the database to create.'),

            make_option('--vmail_username', dest='vmail_username', default='vmail',
                help='Specifies username in the operating system (default=vmail).'),
            make_option('--vmail_uid', dest='vmail_uid', default='5000',
                help='UID of user <vmail_username> (default=5000).'),
            make_option('--vmail_groupname', dest='vmail_groupname', default='vmail',
                help='Specifies the groupname in the operating system (default=vmail).'),
            make_option('--vmail_gid', dest='vmail_gid', default='5000',
                help='GID of user <vmail_username> (default=5000).'),
            make_option('--vmail_home', dest='vmail_home', default='/var/vmail',
                help='$HOME of user <vmail_username> (default=/var/vmail).'),

            make_option('--dovecot_dir', dest='dovecot_dir', default='/etc/dovecot',
                help='Dovecot root directory (default=/etc/dovecot).'),

            make_option('--postfix_dir', dest='postfix_dir', default='/etc/postfix',
                help='Postfix root directory (default=/etc/postfix).'),

            make_option('--amavis_dir', dest='amavis_dir', default='/etc/amavis',
                help='Amavis root directory (default=/etc/amavis).'),

            make_option('--noinput', action='store_false', dest='interactive', default=True,
                help='Tells Django to NOT prompt the user for input of any kind. '
                     'You must use --username with --noinput, and must contain the '
                     'cleeryd process owner, which is the user how will perform tincd updates'),
            )

    option_list = BaseCommand.option_list
    help = 'Setup Postfix.'

    @check_root
    def handle(self, *args, **options):
        # Configure firmware generation
        context = {
            'db_name': options.get('db_name'),
            'db_user': options.get('db_user'),
            'db_password': options.get('db_password'),
            'db_host': options.get('db_host'),
            'vmail_username': options.get('vmail_username'),
            'vmail_uid': options.get('vmail_uid'),
            'vmail_groupname': options.get('vmail_groupname'),
            'vmail_gid': options.get('vmail_gid'),
            'vmail_home': options.get('vmail_home'),
            'dovecot_dir': options.get('dovecot_dir'),
            'postfix_dir': options.get('postfix_dir'),
            'amavis_dir': options.get('amavis_dir'),
        }

        file_name = '%(postfix_dir)s/pgsql-email2email.cf' % context
        run("#Processing %s" % file_name)
        pgsql_email2email = """user = %(db_user)s
password = %(db_password)s
hosts = %(db_host)s
dbname = %(db_name)s

query = SELECT mails_mailbox.emailname || '@' || names_domain.name as email FROM mails_mailbox INNER JOIN names_domain ON (mails_mailbox.domain_id = names_domain.id) WHERE mails_mailbox.emailname = '%%u' AND names_domain.name = '%%d'
"""
        f = open(file_name, 'w')
        f.write(pgsql_email2email % context)
        f.close()
        run("chown root:postfix %s" % file_name)
        run("chmod 640 %s" % file_name)

        file_name = '%(postfix_dir)s/pgsql-virtual-alias-maps.cf' % context
        run("#Processing %s" % file_name)
        virtual_alias_maps = """user = %(db_user)s
password = %(db_password)s
hosts = %(db_host)s
dbname = %(db_name)s

query = SELECT mails_mailalias.destination FROM mails_mailalias INNER JOIN names_domain ON (mails_mailalias.domain_id = names_domain.id) WHERE mails_mailalias.emailname = '%%u' AND names_domain.name='%%d'
"""
        f = open(file_name, 'w')
        f.write(virtual_alias_maps % context)
        f.close()
        run("chown root:postfix %s" % file_name)
        run("chmod 640 %s" % file_name)

        file_name = '%(postfix_dir)s/pgsql-virtual-mailbox-domains.cf' % context
        run("#Processing %s" % file_name)
        virtual_mailbox_domains = """user = %(db_user)s
password = %(db_password)s
hosts = %(db_host)s
dbname = %(db_name)s

query = SELECT 1 FROM names_domain WHERE names_domain.name='%%s'
"""
        f = open(file_name, 'w')
        f.write(virtual_mailbox_domains % context)
        f.close()
        run("chown root:postfix %s" % file_name)
        run("chmod 640 %s" % file_name)

        file_name = '%(postfix_dir)s/pgsql-virtual-mailbox-maps.cf' % context
        run("#Processing %s" % file_name)
        virtual_mailbox_maps = """user = %(db_user)s
password = %(db_password)s
hosts = %(db_host)s
dbname = %(db_name)s

query = SELECT 1 FROM mails_mailbox INNER JOIN names_domain ON (mails_mailbox.domain_id = names_domain.id) WHERE mails_mailbox.emailname='%%u' AND names_domain.name='%%d'
"""
        f = open(file_name, 'w')
        f.write(virtual_mailbox_maps % context)
        f.close()
        run("chown root:postfix %s" % file_name)
        run("chmod 640 %s" % file_name)

        #Dovecot
        vmail_usename = run("id -u %(vmail_username)s" % context)
        vmail_groupname = run("id -g %(vmail_groupname)s" % context)
        if vmail_groupname != context["vmail_gid"]:
            run("groupadd -g %(vmail_gid)s %(vmail_groupname)s" % context)
            run("chown -R %(vmail_username)s:%(vmail_groupname)s %(vmail_home)s" % context)
        if vmail_usename != context["vmail_uid"]:
            run("useradd -g %(vmail_groupname)s -u %(vmail_uid)s %(vmail_username)s -d %(vmail_home)s -m" % context)
            run("chmod u+w %(vmail_home)s" % context)

        run("chown -R %(vmail_username)s:%(vmail_groupname)s %(vmail_home)s" % context)
        run("chmod u+w %(vmail_home)s" % context)

        file_name = "%(dovecot_dir)s/conf.d/10-auth.conf" % context
        run("""sed -i "s/auth_mechanisms = plain$/auth_mechanisms = plain login/g" %s """ % file_name)
        run("""sed -i "s/\#\!include auth-sql.conf.ext/\!include auth-sql.conf.ext/" %s """ % file_name)

        file_name = "%(dovecot_dir)s/conf.d/auth-sql.conf.ext" % context
        run("#Processing %s" % file_name)
        auth_sql_conf_ext = """passdb {
  driver = sql
  args = %(dovecot_dir)s/dovecot-sql.conf.ext
}

userdb {
  driver = static
  args = uid=%(vmail_username)s gid=%(vmail_groupname)s home=%(vmail_home)s/%%d/%%n/Maildir allow_all_users=yes
}
"""
        f = open(file_name, 'w')
        f.write(auth_sql_conf_ext % context)
        f.close()


        file_name = "%(dovecot_dir)s/conf.d/10-mail.conf" % context
        run("#Processing %s" % file_name)
        mail_conf = """mail_location = maildir:%(vmail_home)s/%%d/%%n/Maildir
namespace inbox {
    separator = .
    inbox = yes
}
        """
        f = open(file_name, 'w')
        f.write(mail_conf % context)
        f.close()


        file_name = "%(dovecot_dir)s/conf.d/10-master.conf" % context
        run("""sed -i "s/service auth {/service auth {\\n\\tunix_listener \/var\/spool\/postfix\/private\/auth {\\n\\t\\tmode = 0660\\n\\t\\tuser = postfix\\n\\t\\tgroup = postfix\\n\\t}\\n/g" %s """ % file_name)


        file_name = "%(dovecot_dir)s/conf.d/10-ssl.conf" % context

        run("#Processing %s" % file_name)
        ssl_conf = """ssl_cert = </etc/ssl/certs/mailserver.pem
ssl_key = </etc/ssl/private/mailserver.pem"""
        f = open(file_name, 'w')
        f.write(ssl_conf)
        f.close()

        file_name = "%(dovecot_dir)s/conf.d/15-lda.conf" % context
        run("#Processing %s" % file_name)
        lda_conf ="""protocol lda {
    postmaster_address = postmaster
    mail_plugins = $mail_plugins sieve
}
"""
        f = open(file_name, 'w')
        f.write(lda_conf)
        f.close()


        file_name = "%(dovecot_dir)s/dovecot-sql.conf.ext" % context
        run("#Processing %s" % file_name)
        dovecot_sql = """driver = pgsql
connect = host=%(db_host)s dbname=%(db_name)s user=%(db_user)s password=%(db_password)s
default_pass_scheme = SSHA
password_query = \
 SELECT mails_mailbox.emailname || '@' || names_domain.name as user, mails_mailbox.shadigest as password  \\
    FROM mails_mailbox \\
        INNER JOIN names_domain ON (mails_mailbox.domain_id = names_domain.id) \\
        INNER JOIN auth_user ON (mails_mailbox.user_id = auth_user.id) \\
    WHERE mails_mailbox.emailname = '%%n' AND \\
        names_domain.name = '%%d'
        """
        f = open(file_name, 'w')
        f.write(dovecot_sql % context)
        f.close()


        run("chgrp %(vmail_groupname)s %(dovecot_dir)s/dovecot.conf" % context)
        run("chmod g+r %(dovecot_dir)s/dovecot.conf" % context)

        run("chown root:root %(dovecot_dir)s/dovecot-sql.conf.ext" % context)
        run("chmod go= %(dovecot_dir)s/dovecot-sql.conf.ext" % context)

        file_name = "%(postfix_dir)s/master.cf" % context
        grep_dovecot = run("grep dovecot %s" % file_name, error_codes=[0,1])
        if grep_dovecot == '':
            run("#Processing %s" % file_name)
            dovecot_master="""
dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=%(vmail_username)s:%(vmail_groupname)s argv=/usr/lib/dovecot/dovecot-lda -f ${sender} -d ${recipient}

#Amavis:
amavis unix    -       -       n       -       5     smtp
     -o smtp_data_done_timeout=1200
     -o smtp_send_xforward_command=yes
     -o smtp_tls_note_starttls_offer=no

127.0.0.1:10025 inet n    -       n       -       -     smtpd
    -o content_filter=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_data_restrictions=reject_unauth_pipelining
    -o smtpd_end_of_data_restrictions=
    -o smtpd_restriction_classes=
    -o mynetworks=127.0.0.0/8
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
    -o local_header_rewrite_clients=
    -o smtpd_milters=
    -o local_recipient_maps=
    -o relay_recipient_maps=
              """
            f = open(file_name, 'a')
            f.write(dovecot_master % context)
            f.close()


        #Postfix
        mailname = run("cat /etc/mailname", error_codes=[0,1])
        hostname = run("hostname", error_codes=[0,1])
        if mailname != hostname:
            file_name = "/etc/mailname"
            run("#Processing %s" % file_name)
            f = open(file_name, 'w')
            f.write(hostname % context)
            f.close()


        # Set the base address for all virtual mailboxes
        run("postconf -e virtual_mailbox_base=%(vmail_home)s" % context)

        # A list of all virtual domains serviced by this instance of postfix.
        run("postconf -e virtual_mailbox_domains=pgsql:%(postfix_dir)s/pgsql-virtual-mailbox-domains.cf" % context)

        # Look up the mailbox location based on the email address received.
        run("postconf -e virtual_mailbox_maps=pgsql:%(postfix_dir)s/pgsql-virtual-mailbox-maps.cf" % context)

        # Any aliases that are supported by this system
        run("postconf -e virtual_alias_maps=pgsql:%(postfix_dir)s/pgsql-virtual-alias-maps.cf" % context)

        #Dovecot:
        run("postconf -e virtual_transport=dovecot")
        run("postconf -e dovecot_destination_recipient_limit=1")
        run("postconf -e smtpd_sasl_type=dovecot")
        run("postconf -e smtpd_sasl_path=private/auth")
        run("postconf -e smtpd_sasl_auth_enable=yes")
        if os.path.isfile("/etc/ssl/certs/mailserver.pem"):
            run("postconf -e smtpd_tls_security_level=may")
            run("postconf -e smtpd_tls_auth_only=yes")
            run("postconf -e smtpd_tls_cert_file=/etc/ssl/certs/mailserver.pem")
            run("postconf -e smtpd_tls_key_file=/etc/ssl/private/mailserver.pem")

        run("""postconf -e smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject_invalid_hostname,reject_non_fqdn_recipient,reject_unknown_sender_domain,reject_unknown_recipient_domain,reject_unauth_destination,permit""")
        run("""postconf -e soft_bounce=no""")
        run("""postconf -e content_filter=amavis:[127.0.0.1]:10024""")

        #Amavis:
        file_name = "%(amavis_dir)s/conf.d/15-content_filter_mode" % context
        run("""sed -i "s/#@bypass_virus_checks_maps/@bypass_virus_checks_maps/g" %s""" % file_name)
        run("""sed -i 's/#   \\\\%%bypass_virus_checks, \\\@bypass_virus_checks_acl, \\\$bypass_virus_checks_re/   \\\\%%bypass_virus_checks, \\\@bypass_virus_checks_acl, \\\$bypass_virus_checks_re/g' %s""" % file_name)
        run("""sed -i 's/#   \\\\%%bypass_virus_checks/   \\\\%%bypass_virus_checks/g' %s""" % (file_name,) )
        run("""sed -i "s/#@bypass_spam_checks_maps/@bypass_spam_checks_maps/g" %s""" % file_name)
        run("""sed -i 's/#   \\\\%%bypass_spam_checks, \\\@bypass_spam_checks_acl, \\\$bypass_spam_checks_re/   \\\\%%bypass_spam_checks, \\\@bypass_spam_checks_acl, \\\$bypass_spam_checks_re/g' %s""" % file_name)

        run("adduser clamav amavis")

        run("service clamav-freshclam restart")
        run("service clamav-daemon restart")
        run("service spamassassin restart")
        run("service amavis restart")
        run("service dovecot restart")
        run("service postfix restart")
