import os
import re
import urllib

from quixote import get_publisher, get_request

from larpe import misc
from larpe.hosts import Host

def write_apache2_vhosts():
    hosts = Host.select(lambda x: x.name != 'larpe')
    hosts.sort()
    hosts.reverse()
    global_app_dir = os.path.join(get_publisher().app_dir, '..')
    vhosts_dir = os.path.join(global_app_dir, 'vhosts.d')
    vhost_locations_dir = os.path.join(global_app_dir, 'vhost-locations.d')
    vhosts_dir_disabled = os.path.join(global_app_dir, 'vhosts.d.disabled')
    vhost_locations_dir_disabled = os.path.join(global_app_dir, 'vhost-locations.d.disabled')
    vhost_file_name = get_request().get_server().split(':')[0]
    vhost_file = None
    reversed_hostname = ''
    other_locations_cfg = []

    if misc.cfg.get(str('allow_config_generation'), True):
        vhost_file = open(os.path.join(vhosts_dir, vhost_file_name), 'w')
        locations_file = open(os.path.join(vhost_locations_dir, vhost_file_name), 'w')
    else:
        vhost_file = open(os.path.join(vhosts_dir_disabled, vhost_file_name), 'w')
        locations_file = open(os.path.join(vhost_locations_dir_disabled, vhost_file_name), 'w')
    try:
        main_vhost = open('/etc/apache2/sites-available/apache2-vhost-larpe', 'r')
        file_content = main_vhost.read()
        regexp = re.compile('<VirtualHost (.*?)>')
        vhost_ip = regexp.findall(file_content)[0]
    except:
        vhost_ip = '*'

#        vhost_file.write('NameVirtualHost %s\n' % vhost_ip)

    for host in hosts:
        cfg = get_vhost_cfg(host, vhost_ip)
        if host.reversed_hostname != reversed_hostname and host.reversed_hostname != misc.cfg['proxy_hostname']:
            write_new_vhost(vhost_file, host, cfg, reversed_hostname)
            reversed_hostname = host.reversed_hostname

        if host.reversed_hostname == misc.cfg['proxy_hostname']:
            conf_file = locations_file
        else:
            conf_file = vhost_file

        write_location(conf_file, cfg)

        if host.reversed_directory is None:
            for other_cfg in other_locations_cfg:
                # Needed because otherwise most of the location configuration wasn't read by apache
                write_location(conf_file, other_cfg)
            other_locations_cfg = []
        elif host.reversed_hostname != misc.cfg['proxy_hostname']:
            other_locations_cfg.append(cfg)


    if vhost_file is not None and reversed_hostname != '':
        vhost_file.write('</VirtualHost>\n')
        vhost_file.close()
    if locations_file is not None:
        locations_file.close()

    if misc.cfg.get(str('allow_config_generation'), True):
        os.system('/usr/sbin/larpe-reload-apache2')

def get_vhost_cfg(host, vhost_ip):
    if host.orig_site.startswith('http://'):
        orig_host, orig_query = urllib.splithost(host.orig_site[5:])
    else:
        orig_host, orig_query = urllib.splithost(host.orig_site[6:])

    if host.orig_site.endswith('/'):
        orig_site = host.orig_site
        orig_dir = orig_query
    else:
        orig_site = host.orig_site + '/'
        orig_dir = orig_query + '/'

    if host.use_ssl:
        vhost_ip = vhost_ip.replace(':80', ':443')
    else:
        vhost_ip = vhost_ip.replace(':443', ':80')

    old_auth_url = None
    if host.auth_url is not None:
        if host.auth_url.startswith('http://'):
            chars_to_skip = 5
        else:
            chars_to_skip = 6
        regexp = re.compile(host.orig_site[chars_to_skip:])
        old_auth_url_short = regexp.sub('', host.auth_url[chars_to_skip:])
        if old_auth_url_short.startswith('/'):
            old_auth_url = old_auth_url_short
        else:
            old_auth_url = '/' + old_auth_url_short
        special_characters = ('\\', '.', '?', '*', '+', '^', '$', '|', '(', ')', '[', ']')
        for char in special_characters:
            old_auth_url = old_auth_url.replace(char, '\%s' % char)

    base_url_tokens = host.base_url.split('/')
    base_url_tokens[-1] = 'login'
    new_auth_url = '/'.join(base_url_tokens)

    old_logout_url = None
    new_logout_url = None
    if host.logout_url is not None:
        if host.logout_url.startswith('http://'):
            chars_to_skip = 5
        else:
            chars_to_skip = 6
        regexp = re.compile(host.orig_site[chars_to_skip:])
        old_logout_url_short = regexp.sub('', host.logout_url[chars_to_skip:])
        if old_logout_url_short.startswith('/'):
            old_logout_url = old_logout_url_short
        else:
            old_logout_url = '/' + old_logout_url_short
        special_characters = ('\\', '.', '?', '*', '+', '^', '$', '|', '(', ')', '[', ']')
        for char in special_characters:
            old_logout_url = old_logout_url.replace(char, '\%s' % char)

        base_url_tokens = host.base_url.split('/')
        base_url_tokens[-1] = 'logout'
        new_logout_url = '/'.join(base_url_tokens)

    cfg = { 'vhost_ip': vhost_ip,
            'reversed_hostname': host.reversed_hostname,
            'orig_site': orig_site,
            'orig_dir': orig_dir,
            'old_auth_url': old_auth_url,
            'new_auth_url': new_auth_url,
            'old_logout_url': old_logout_url,
            'new_logout_url': new_logout_url }

    if host.reversed_directory is None:
        cfg['reversed_directory'] = '%s/' % get_request().environ['SCRIPT_NAME']
    else:
        cfg['reversed_directory'] = '%s/%s/' % (get_request().environ['SCRIPT_NAME'], host.reversed_directory)

    return cfg


def write_new_vhost(vhost_file, host, cfg, reversed_hostname):
    if reversed_hostname != '' and reversed_hostname != misc.cfg['proxy_hostname']:
        vhost_file.write('</VirtualHost>\n\n')
    vhost_file.write("""<VirtualHost %(vhost_ip)s>
    ServerName %(reversed_hostname)s
    # ServerAdmin root@localhost

    include /usr/share/larpe/apache2.conf
""" % cfg)

    if host.use_ssl:
        vhost_file.write("""
    SSLEngine on
""")

    if host.orig_site.startswith('https'):
        vhost_file.write("""
    SSLProxyEngine on
""")


def write_location(conf_file, cfg):
    conf_file.write("""
    <Location %(reversed_directory)s>
        Allow from all""" % cfg)

    if cfg['old_auth_url'] is not None or cfg['old_logout_url'] is not None:
        conf_file.write("""
        RewriteEngine on""")

    if cfg['old_auth_url'] is not None:
        conf_file.write("""
        RewriteRule         %(old_auth_url)s     %(new_auth_url)s  [R]""" % cfg)

    if cfg['old_logout_url'] is not None:
        conf_file.write("""
        RewriteRule         %(old_logout_url)s     %(new_logout_url)s  [R]""" % cfg)

    conf_file.write("""
        ProxyPass           %(orig_site)s
        ProxyPassReverse    %(orig_site)s
        ProxyHTMLURLMap     %(orig_dir)s     %(reversed_directory)s
        ProxyHTMLURLMap     %(orig_site)s    %(reversed_directory)s
    </Location>
""" % cfg)                
