from optparse import make_option
from os.path import expanduser

from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils.six.moves import input

from orchestra.utils.paths import get_project_root, get_site_root, get_project_name
from orchestra.utils.system import run, check_root, get_default_celeryd_username


class Command(BaseCommand):
    def __init__(self, *args, **kwargs):
        super(Command, self).__init__(*args, **kwargs)
        self.option_list = BaseCommand.option_list + (
            make_option('--user', dest='user', default=get_default_celeryd_username(),
                help='uWSGI daemon user.'),
            make_option('--group', dest='group', default='',
                help='uWSGI daemon group.'),
            make_option('--processes', dest='processes', default=4,
                help='uWSGI number of processes.'),
            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 = 'Configures nginx + uwsgi to run with your Orchestra instance.'
    
    @check_root
    def handle(self, *args, **options):
        interactive = options.get('interactive')
        
        context = {
            'project_name': get_project_name(),
            'project_root': get_project_root(),
            'site_root': get_site_root(),
            'static_root': settings.STATIC_ROOT,
            'user': options.get('user'),
            'group': options.get('group') or options.get('user'),
            'home': expanduser("~%s" % options.get('user')),
            'processes': int(options.get('processes')),}
        
        nginx_conf = (
            'server {\n'
            '    listen 80;\n'
            '    listen [::]:80 ipv6only=on;\n'
            '    rewrite ^/$ /admin/;\n'
            '    client_max_body_size 500m;\n'
            '    location / {\n'
            '        uwsgi_pass unix:///var/run/uwsgi/app/%(project_name)s/socket;\n'
            '        include uwsgi_params;\n'
            '    }\n'
            '    location /static {\n'
            '        alias %(static_root)s;\n'
            '        expires 30d;\n'
            '    }\n'
            '}\n') % context
        
        uwsgi_conf = (
            '[uwsgi]\n'
            'plugins      = python\n'
            'chdir        = %(site_root)s\n'
            'module       = %(project_name)s.wsgi\n'
            'master       = true\n'
            'processes    = %(processes)d\n'
            'chmod-socket = 664\n'
            'stats        = /run/uwsgi/%%(deb-confnamespace)/%%(deb-confname)/statsocket\n'
            'vacuum       = true\n'
            'uid          = %(user)s\n'
            'gid          = %(group)s\n'
            'env          = HOME=%(home)s\n') % context
        
        nginx = {
            'file': '/etc/nginx/conf.d/%(project_name)s.conf' % context,
            'conf': nginx_conf }
        uwsgi = {
            'file': '/etc/uwsgi/apps-available/%(project_name)s.ini' % context,
            'conf': uwsgi_conf }
        
        for extra_context in (nginx, uwsgi):
            context.update(extra_context)
            diff = run("echo '%(conf)s'|diff - %(file)s" % context, error_codes=[0,1,2])
            if diff.return_code == 2:
                # File does not exist
                run("echo '%(conf)s' > %(file)s" % context)
            elif diff.return_code == 1:
                # File is different, save the old one
                if interactive:
                    msg = ("\n\nFile %(file)s be updated, do you like to overide "
                           "it? (yes/no): " % context)
                    confirm = input(msg)
                    while 1:
                        if confirm not in ('yes', 'no'):
                            confirm = input('Please enter either "yes" or "no": ')
                            continue
                        if confirm == 'no':
                            return
                        break
                run("cp %(file)s %(file)s.save" % context)
                run("echo '%(conf)s' > %(file)s" % context)
                self.stdout.write("\033[1;31mA new version of %(file)s has been installed.\n "
                    "The old version has been placed at %(file)s.save\033[m" % context)
        
        run('ln -s /etc/uwsgi/apps-available/%(project_name)s.ini /etc/uwsgi/apps-enabled/' % context, error_codes=[0,1])
        
        # nginx should start after tincd
        current = "\$local_fs \$remote_fs \$network \$syslog"
        run('sed -i "s/  %s$/  %s \$named/g" /etc/init.d/nginx' % (current, current))
        
        rotate = (
            '/var/log/nginx/*.log {\n'
            '    daily\n'
            '    missingok\n'
            '    rotate 30\n'
            '    compress\n'
            '    delaycompress\n'
            '    notifempty\n'
            '    create 640 root adm\n'
            '    sharedscripts\n'
            '    postrotate\n'
            '        [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`\n'
            '    endscript\n'
            '}\n')
        run("echo '%s' > /etc/logrotate.d/nginx" % rotate)
        
        # Allow nginx to write to uwsgi socket
        run('adduser www-data %(group)s' % context)