# -*- coding: UTF-8 -*-


# Expression
# By: Frederic Peters <fpeters@entrouvert.com>
#     Emmanuel Raviart <eraviart@entrouvert.com>
#
# Copyright (C) 2004 Entr'ouvert, Frederic Peters & Emmanuel Raviart
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.


"""URIs Module."""


import os
import types
import urllib

import environs


def appendParameterToUrl(url, name, value):
    if type(value) in (types.ListType, types.TupleType):
        for item in value:
            url = appendParameterToUrl(url, name, item)
        return url
    if "?" in url:
        separator = "&"
    else:
        separator = "?"
    # Note: We don't call urllib.quote(x), but urllib.quote(x, ""), because
    # we also want "/" to be quoted. Otherwise, the quoting is not the same as
    # libxml2, wich is a problem when verifying url signatures (used by Liberty
    # Alliance). FIXME: Check that lasso uses the right quoting function.
    return "%s%s%s=%s" % (url, separator, name, urllib.quote(str(value), ""))


def cleanUpQuery(query, *parameterNamesToRemove):
    splitedQuery = query.split("&")
    cleanedQuery = ""
    separator = ""
    for parameter in splitedQuery:
        name, value = parameter.split("=", 1)
        if name not in parameterNamesToRemove:
            cleanedQuery = "%s%s%s=%s" % (cleanedQuery, separator, name, value)
            separator = "&"
    return cleanedQuery


def cleanUpUrl(url, *parameterNamesToRemove):
    splitedUrl = url.split("?", 1)
    if len(splitedUrl) < 2:
        return url
    cleanedQuery = cleanUpQuery(splitedUrl[1], *parameterNamesToRemove)
    if not cleanedQuery:
        return splitedUrl[0]
    return "%s?%s" % (splitedUrl[0], cleanedQuery)


def constructUri(location, preserveAbsolutePath = False):
    """Return the best URI to use inside web pages."""

    if location.find(":", 0, 10) >= 0:
        # Don't touch location if it begins with "http:", "mailto", etc. 
        return location
    else:
        # We assume that location is a relative URI whithout
        # "file://" prefix.
        uri = constructUriAbsolutePath(
            location, preserveAbsolutePath = preserveAbsolutePath)
        uri = cleanUpUrl(uri, "sessionToken")
        if not environs.getVar("canUseCookie") \
               or environs.getVar("testCookieSupport"):
            session = environs.getVar("session")
            if session is not None and session.publishToken:
                uri = appendParameterToUrl(uri, "sessionToken", session.token)
        return uri


def constructUriAbsolutePath(location, preserveAbsolutePath = False):
    # Assume that location is a relative URI without "file://" prefix.
    if location.startswith("//"):
        # Relative URI with network path
        raise "TODO"
    elif location and location[0] == "/":
        # Relative URI with absolute path.
        if preserveAbsolutePath:
            return location
        else:
            absolutePath = environs.getVar("httpScriptDirectoryPath")
            if absolutePath[-1] == "/":
                return "%s%s" % (absolutePath, location[1:])
            else:
                return "%s/%s" % (absolutePath, location[1:])
    else:
        raise Exception("""Location "%s" is not an absolute path. Use method Station.constructUriAbsolutePath instead.""" % location)

def extractUriLocalId(location):
    return location.split("/")[-1]


def extractUriHostName(location):
    if "://" in location:
        authority = location[location.index("://") + 3:].split("/", 1)[0]
    else:
        authority = environs.getVar("uriAuthority")
    if "@" in authority:
        authority = authority.split("@", 1)[1]
    hostName = authority.split(":", 1)[0]
    return hostName


def isLocalUri(location):
    authority = environs.getVar("uriAuthority")
    if "@" in authority:
        authority = authority.split("@", 1)[1]
    hostName = authority.split(":", 1)[0]
    return extractUriHostName(location) == hostName


def removeSessionFromUrl(url):
    url = cleanUpUrl(url, "sessionToken")
    virtualHost = environs.getVar("virtualHost")
    if virtualHost.isSsl and virtualHost.brotherVirtualHost is not None:
        # We are currently in HTTPS => redirect to HTTP.
        uriAuthority = environs.getVar("uriAuthority")
        i = uriAuthority.find("@") + 1
        j = uriAuthority.find(":", i)
        if j >= 0:
            uriAuthority = uriAuthority[:j]
        httpPort = virtualHost.brotherVirtualHost.getPort()
        if httpPort != 80:
            uriAuthority = "%s:%d" % (uriAuthority, httpPort)
        urlAbsolutePath = constructUriAbsolutePath(url, preserveAbsolutePath = True)
        url = "http://%s%s" % (uriAuthority, urlAbsolutePath)
    else:
        url = constructUri(url, preserveAbsolutePath = True)
    return url
