import subprocess
import urlparse
import syslog
import re

from django.conf import settings

from django.shortcuts import render_to_response
from django.template import RequestContext
from django.shortcuts import redirect
from django.contrib import messages
from django.http import HttpResponse
import django.contrib.auth

from authentic2.authsaml2.utils import register_next_target
from authentic2.authsaml2.saml2_endpoints import sso as authentic2_sso
import authentic2.saml.models as saml_models

import pfsense

from forms import MailForm, EMAIL_SUBJECTS_CHOICES, IDP_CHOICES
from django.core.mail import send_mail


def redirect302(request):
    next_url = 'http://' + request.META['HTTP_HOST'] + request.META['REQUEST_URI']
    # don't redirect to login page if URL is not really a web page,
    # so don't create a sessiona and just stop here
    for bl in settings.FIRST_URL_BLACKLIST:
        if re.match(bl, next_url):
            return HttpResponse("eduspot", content_type="text/plain", status=503)
    return redirect('https://%s/login?next_url=%s' % (settings.HTTPS_HOSTNAME, next_url))

def index(request):
    if not 'pfsenseid' in request.session:
        return redirect('/login')
    pfsenseid = request.session['pfsenseid']
    # dirty hack to handle errors and blacklisted users (see auth.py)
    if pfsenseid in ('BLACKLISTED', 'ERROR'):
        django.contrib.auth.logout(request)
        return redirect('/login')
    if 'next_url' in request.session:
        # display next_url and forget it
        next_url = request.session['next_url']
        del request.session['next_url']
        request.session.set_expiry(settings.SESSION_COOKIE_AGE)
    else:
        next_url = None
    if 'display_name' in request.session:
        display_name = request.session['display_name']
    else:
        display_name = ''
    pfsense_session = pfsense.get_captive_portal_session(ip = request.META['REMOTE_ADDR'])
    if settings.REDIRECT_URL:
        values = {
                'next_url': next_url,
                'redirect_delay': settings.REDIRECT_DELAY,
                'display_name': display_name,
                'pfsenseid': pfsenseid,
                }
        values.update(pfsense_session)
        next_url = settings.REDIRECT_URL % values
    if settings.REDIRECT_DELAY == 0 and next_url != None:
        response = redirect(next_url)
    else:
        try:
            next_url_host = urlparse.urlsplit(next_url)[1]
        except:
            next_url_host = next_url
        if settings.EMAIL_RCPT and settings.EMAIL_HOST:
            mailform = True
        else:
            mailform = False
        response = render_to_response('index.html',
           {'next_url': next_url, 
            'next_url_host': next_url_host,
            'redirect_delay': settings.REDIRECT_DELAY,
            'display_name': display_name,
            'pfsenseid': pfsenseid,
            'pfsense_session': pfsense_session,
            'prefered_idp': request.session.get('prefered_idp', ''),
            'mailform': mailform,
            'https_hostname': settings.HTTPS_HOSTNAME,
            },
           context_instance=RequestContext(request))
    # store prefered_idp in a cookie with a ten days ttl
    if 'prefered_idp' in request.session:
        response.set_cookie('prefered_idp', request.session['prefered_idp'], max_age=10*24*3600)
    return response

def login(request):
    # if we are already logged (or supposed to be), go to index
    if 'pfsenseid' in request.session:
        return redirect('/')
    if 'next_url' in request.GET:
        request.session['next_url'] = request.GET['next_url']
    else:
        request.session['next_url'] = None
    try:
        prefered_idp = request.COOKIES.get('prefered_idp', settings.DEFAULT_IDP)
        default_idp = saml_models.LibertyProvider.objects.get(entity_id=prefered_idp)
    except:
        try:
            default_idp = saml_models.LibertyProvider.objects.get(entity_id=settings.DEFAULT_IDP)
        except:
            default_idp = None
    register_next_target(request, url='/')
    if settings.EMAIL_RCPT and settings.EMAIL_HOST:
        mailform = True
    else:
        mailform = False
    request.session.set_expiry(60)
    return render_to_response('login.html',
           {'default_idp': default_idp,
            'mailform': mailform,
            'https_hostname': settings.HTTPS_HOSTNAME,
            'disco_stores_read': settings.DISCO_STORES_READ,
            'disco_stores_write': settings.DISCO_STORES_WRITE,
            'start_bounds': settings.GEO_START_BOUNDS,
            },
           context_instance=RequestContext(request))

def sso(request, is_passive=None, force_authn=None, http_method=None):
    '''log a sso request and send it to authentic2'''
    entity_id = request.REQUEST.get('entity_id')
    ip = request.META['REMOTE_ADDR']
    mac = pfsense.get_mac_from_ip(ip)
    syslog.openlog("logportalauth", syslog.LOG_PID)
    syslog.syslog(syslog.LOG_LOCAL4 | syslog.LOG_INFO , "SSOREDIRECT: %s,%s to %s" % (ip, mac, entity_id))
    return authentic2_sso(request, is_passive=is_passive, force_authn=force_authn, http_method=http_method)

def logout(request):
    if 'pfsenseid' in request.session:
        pfsenseid = request.session['pfsenseid']
    else:
        pfsenseid = None
    ip = request.META['REMOTE_ADDR']
    django.contrib.auth.logout(request)
    if pfsenseid:
        cmd = ['cp_disconnect', 'sessionid=%s' % pfsenseid, 'ip=%s' % ip]
    else:
        cmd = ['cp_disconnect', 'ip=%s' % ip ]
    try:
        p = subprocess.Popen(cmd, close_fds=True,
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
    except OSError, e:
        return
    stdout, stderr = p.communicate()

    return redirect('/login')

def mail(request):
    if request.method == 'POST':
        form = MailForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['name']
            from_email = form.cleaned_data['from_email']
            idp = form.cleaned_data['idp']
            idp_name = dict(IDP_CHOICES).get(idp)
            phone = form.cleaned_data.get('phone', '')
            n_subject = form.cleaned_data['subject']
            subject = dict(EMAIL_SUBJECTS_CHOICES).get(n_subject, 'unknown subject ?')
            body = form.cleaned_data['body']
            total_body = u'Nom: %(name)s <%(from_email)s>\nTel: %(phone)s\n' \
                    'IdP: %(idp_name)s <%(idp)s>\n\n' \
                    'Message:\n%(body)s\n\n-- \nUnivNautes\n' % {
                            'name': name, 'from_email': from_email,
                            'idp': idp or None, 'idp_name': idp_name,
                            'phone': phone,
                            'body': body }
            try:
                send_mail(u'[Contact UnivNautes] %s' % subject,
                        total_body,
                        u'%s' % from_email,
                        [settings.EMAIL_RCPT],
                        fail_silently=False)
            except Exception, e:
                messages.add_message(request, messages.ERROR, 'send_mail error: %s' % e)
            else:
                response = redirect('.')
                return response
    else:
        form = MailForm()
    return render_to_response('mail.html',
            { 'form': form, },
            context_instance=RequestContext(request))

