import cPickle
import re
import os
import time
import httplib
import urllib
import socket

import lasso

from quixote import get_publisher, get_request

from hosts import Host

def get_abs_path(s):
    if not s:
        return s
    if s[0] == '/':
        return s
    return os.path.join(get_publisher().app_dir, s)

def get_root_url():
    req = get_request()
    return '%s://%s%s' % (req.get_scheme(), req.get_server(), req.environ['SCRIPT_NAME'])

def get_proxied_site_path():
    host = Host.get_host_from_url()
    if host is None:
        return None
    return host.site_dir

def get_proxied_site_domain():
    return get_request().get_server().split(':')[0]

def get_proxied_site_name():
    nb_subdirs = get_request().environ['SCRIPT_NAME'].count('/')
    return get_request().get_path().split('/')[nb_subdirs + 2]

def get_lasso_server(protocol = 'liberty'):
    host = Host.get_host_from_url()
    if host is None:
        return None
    proxied_site_path = get_proxied_site_path()
    if protocol == 'liberty':
        server = lasso.Server(
            os.path.join(proxied_site_path, 'metadata.xml'),
            os.path.join(proxied_site_path, 'private_key.pem'),
            None, None)
#     elif protocol == 'saml2' and cfg['sp'].has_key('saml2_metadata'):
#         server = lasso.Server(
#             os.path.join(proxied_site_path, 'metadata.xml'),
#             os.path.join(proxied_site_path, 'private_key.pem'),
#             None, None)
    else:
        raise 'XXX: unknown protocol'

    reload_cfg()    
    idps_dir = get_abs_path('idp')
#    for idp_name in host.idps:
    if cfg.has_key('idp'):
        idp_dir = os.path.join(idps_dir, cfg['idp'])
        ca_cert_chain = os.path.join(idp_dir, 'ca_cert_chain.pem')
        if not os.path.isfile(ca_cert_chain):
            ca_cert_chain = None
        try:
            server.addProvider(
                    lasso.PROVIDER_ROLE_IDP,
                    os.path.join(idp_dir, 'metadata.xml'),
                    os.path.join(idp_dir, 'public_key.pem'),
                    ca_cert_chain)
        except lasso.Error, error:
            if error[0] == -203: # protocol mismatch
                pass
                #continue
            if error[0] == -202: # failed to add new provider
                pass
                #continue
            raise

    return server

def get_provider_label(provider):
    if not provider:
        return None
    if not hasattr(provider, str('getOrganization')):
        return provider.providerId

    organization = provider.getOrganization()
    if not organization:
        return provider.providerId

    name = re.findall("<OrganizationDisplayName.*>(.*?)</OrganizationDisplayName>", organization)
    if not name:
        name = re.findall("<OrganizationName.*>(.*?)</OrganizationName>", organization)
        if not name:
            return provider.providerId
    return name[0]


def write_cfg(directory = None):
    s = cPickle.dumps(cfg)
    if directory is None:
        filename = os.path.join(get_publisher().app_dir, 'config.pck')
    else:
        filename = os.path.join(directory, 'config.pck')
    file(filename, 'w').write(s)

def reload_cfg():
    global cfg
    filename = os.path.join(get_publisher().app_dir, 'config.pck')
    try:
        cfg = cPickle.load(file(filename))
        cfg['debug'] = {}
        cfg['debug']['logger'] = True
    except:
        cfg = {}


# xlate = {
#     u'\N{ACUTE ACCENT}': "'",
#     u'\N{BROKEN BAR}': '|',
#     u'\N{CEDILLA}': '{cedilla}',
#     u'\N{CENT SIGN}': '{cent}',
#     u'\N{COPYRIGHT SIGN}': '{C}',
#     u'\N{CURRENCY SIGN}': '{currency}',
#     u'\N{DEGREE SIGN}': '{degrees}',
#     u'\N{DIAERESIS}': '{umlaut}',
#     u'\N{DIVISION SIGN}': '/',
#     u'\N{FEMININE ORDINAL INDICATOR}': '{^a}',
#     u'\N{INVERTED EXCLAMATION MARK}': '!',
#     u'\N{INVERTED QUESTION MARK}': '?',
#     u'\N{LATIN CAPITAL LETTER A WITH ACUTE}': 'A',
#     u'\N{LATIN CAPITAL LETTER A WITH CIRCUMFLEX}': 'A',
#     u'\N{LATIN CAPITAL LETTER A WITH DIAERESIS}': 'A',
#     u'\N{LATIN CAPITAL LETTER A WITH GRAVE}': 'A',
#     u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}': 'A',
#     u'\N{LATIN CAPITAL LETTER A WITH TILDE}': 'A',
#     u'\N{LATIN CAPITAL LETTER AE}': 'Ae',
#     u'\N{LATIN CAPITAL LETTER C WITH CEDILLA}': 'C',
#     u'\N{LATIN CAPITAL LETTER E WITH ACUTE}': 'E',
#     u'\N{LATIN CAPITAL LETTER E WITH CIRCUMFLEX}': 'E',
#     u'\N{LATIN CAPITAL LETTER E WITH DIAERESIS}': 'E',
#     u'\N{LATIN CAPITAL LETTER E WITH GRAVE}': 'E',
#     u'\N{LATIN CAPITAL LETTER ETH}': 'Th',
#     u'\N{LATIN CAPITAL LETTER I WITH ACUTE}': 'I',
#     u'\N{LATIN CAPITAL LETTER I WITH CIRCUMFLEX}': 'I',
#     u'\N{LATIN CAPITAL LETTER I WITH DIAERESIS}': 'I',
#     u'\N{LATIN CAPITAL LETTER I WITH GRAVE}': 'I',
#     u'\N{LATIN CAPITAL LETTER N WITH TILDE}': 'N',
#     u'\N{LATIN CAPITAL LETTER O WITH ACUTE}': 'O',
#     u'\N{LATIN CAPITAL LETTER O WITH CIRCUMFLEX}': 'O',
#     u'\N{LATIN CAPITAL LETTER O WITH DIAERESIS}': 'O',
#     u'\N{LATIN CAPITAL LETTER O WITH GRAVE}': 'O',
#     u'\N{LATIN CAPITAL LETTER O WITH STROKE}': 'O',
#     u'\N{LATIN CAPITAL LETTER O WITH TILDE}': 'O',
#     u'\N{LATIN CAPITAL LETTER THORN}': 'th',
#     u'\N{LATIN CAPITAL LETTER U WITH ACUTE}': 'U',
#     u'\N{LATIN CAPITAL LETTER U WITH CIRCUMFLEX}': 'U',
#     u'\N{LATIN CAPITAL LETTER U WITH DIAERESIS}': 'U',
#     u'\N{LATIN CAPITAL LETTER U WITH GRAVE}': 'U',
#     u'\N{LATIN CAPITAL LETTER Y WITH ACUTE}': 'Y',
#     u'\N{LATIN SMALL LETTER A WITH ACUTE}': 'a',
#     u'\N{LATIN SMALL LETTER A WITH CIRCUMFLEX}': 'a',
#     u'\N{LATIN SMALL LETTER A WITH DIAERESIS}': 'a',
#     u'\N{LATIN SMALL LETTER A WITH GRAVE}': 'a',
#     u'\N{LATIN SMALL LETTER A WITH RING ABOVE}': 'a',
#     u'\N{LATIN SMALL LETTER A WITH TILDE}': 'a',
#     u'\N{LATIN SMALL LETTER AE}': 'ae',
#     u'\N{LATIN SMALL LETTER C WITH CEDILLA}': 'c',
#     u'\N{LATIN SMALL LETTER E WITH ACUTE}': 'e',
#     u'\N{LATIN SMALL LETTER E WITH CIRCUMFLEX}': 'e',
#     u'\N{LATIN SMALL LETTER E WITH DIAERESIS}': 'e',
#     u'\N{LATIN SMALL LETTER E WITH GRAVE}': 'e',
#     u'\N{LATIN SMALL LETTER ETH}': 'th',
#     u'\N{LATIN SMALL LETTER I WITH ACUTE}': 'i',
#     u'\N{LATIN SMALL LETTER I WITH CIRCUMFLEX}': 'i',
#     u'\N{LATIN SMALL LETTER I WITH DIAERESIS}': 'i',
#     u'\N{LATIN SMALL LETTER I WITH GRAVE}': 'i',
#     u'\N{LATIN SMALL LETTER N WITH TILDE}': 'n',
#     u'\N{LATIN SMALL LETTER O WITH ACUTE}': 'o',
#     u'\N{LATIN SMALL LETTER O WITH CIRCUMFLEX}': 'o',
#     u'\N{LATIN SMALL LETTER O WITH DIAERESIS}': 'o',
#     u'\N{LATIN SMALL LETTER O WITH GRAVE}': 'o',
#     u'\N{LATIN SMALL LETTER O WITH STROKE}': 'o',
#     u'\N{LATIN SMALL LETTER O WITH TILDE}': 'o',
#     u'\N{LATIN SMALL LETTER SHARP S}': 'ss',
#     u'\N{LATIN SMALL LETTER THORN}': 'th',
#     u'\N{LATIN SMALL LETTER U WITH ACUTE}': 'u',
#     u'\N{LATIN SMALL LETTER U WITH CIRCUMFLEX}': 'u',
#     u'\N{LATIN SMALL LETTER U WITH DIAERESIS}': 'u',
#     u'\N{LATIN SMALL LETTER U WITH GRAVE}': 'u',
#     u'\N{LATIN SMALL LETTER Y WITH ACUTE}': 'y',
#     u'\N{LATIN SMALL LETTER Y WITH DIAERESIS}': 'y',
#     u'\N{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}': '<<',
#     u'\N{MACRON}': '_',
#     u'\N{MASCULINE ORDINAL INDICATOR}': '{^o}',
#     u'\N{MICRO SIGN}': '{micro}',
#     u'\N{MIDDLE DOT}': '*',
#     u'\N{MULTIPLICATION SIGN}': '*',
#     u'\N{NOT SIGN}': '{not}',
#     u'\N{PILCROW SIGN}': '{paragraph}',
#     u'\N{PLUS-MINUS SIGN}': '{+/-}',
#     u'\N{POUND SIGN}': '{pound}',
#     u'\N{REGISTERED SIGN}': '{R}',
#     u'\N{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}': '>>',
#     u'\N{SECTION SIGN}': '{section}',
#     u'\N{SOFT HYPHEN}': '-',
#     u'\N{SUPERSCRIPT ONE}': '{^1}',
#     u'\N{SUPERSCRIPT THREE}': '{^3}',
#     u'\N{SUPERSCRIPT TWO}': '{^2}',
#     u'\N{VULGAR FRACTION ONE HALF}': '{1/2}',
#     u'\N{VULGAR FRACTION ONE QUARTER}': '{1/4}',
#     u'\N{VULGAR FRACTION THREE QUARTERS}': '{3/4}',
#     u'\N{YEN SIGN}': '{yen}'
#     }

# def latin1_to_ascii (unicrap):
#     """This takes a UNICODE string and replaces Latin-1 characters with
#         something equivalent in 7-bit ASCII. It returns a plain ASCII string. 
#         This function makes a best effort to convert Latin-1 characters into 
#         ASCII equivalents. It does not just strip out the Latin-1 characters.
#         All characters in the standard 7-bit ASCII range are preserved. 
#         In the 8th bit range all the Latin-1 accented letters are converted 
#         to unaccented equivalents. Most symbol characters are converted to 
#         something meaningful. Anything not converted is deleted.

#         <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/251871>
#     """

#     if not isinstance(unicrap, unicode):
#         unicrap = unicode(unicrap, 'iso-8859-1')
#     r = ""
#     for i in unicrap:
#         if xlate.has_key(i):
#             r += xlate[i]
#         elif ord(i) >= 0x80:
#             pass
#         else:
#             r += str(i)
#     return r

# simplifyRegex = re.compile(r'''([\s()'"/:\.,\&]+)''')

# def simplify(s, space = '-'):
#     if s is None: s = ''
#     s = latin1_to_ascii(simplifyRegex.sub(' ', s).strip()).replace(' ', space).lower()
#     return s


# def localstrftime(t):
#     if not t:
#         return ''
#     format_string = '%Y-%m-%d %H:%M'
#     lang = cfg.get('language', {}).get('language', None)
#     if lang == 'fr' or (lang is None and os.environ.get('LC_ALL', '')[:2] == 'fr'):
#         format_string = '%d/%m/%Y %H:%M'
#     return time.strftime(format_string, t)

def date_format():
    lang = cfg.get('language', {}).get('language', None)
    format_string = '%Y-%m-%d'
    return format_string

# def ellipsize(s, length = 30):
#     if not s or len(s) < length:
#         return s
#     return s[:length-5] + ' (...)'

def get_html_page(url):
    if url.startswith('http://'):
        hostname, query = urllib.splithost(url[5:])
        conn = httplib.HTTPConnection(hostname)
    else:
        hostname, query = urllib.splithost(url[6:])
        conn = httplib.HTTPSConnection(hostname)
    try:
        conn.request('GET', query)
    except socket.gaierror, err:
        print err
        conn.close()
        return 0, None
    else:
        response = conn.getresponse()
        data = response.read()
        status = response.status
        auth_header = response.getheader('WWW-Authenticate')
        conn.close()
    return status, data, auth_header
