# -*- coding: utf-8 -*-
#-
# :Copyright: (c) 2015-2018, Franz Glasner. All rights reserved.
# :License:   3-clause BSD. See LICENSE.txt for details.
#-
"""Variable expansion: implementation of namespaces and filters

"""

from __future__ import division, absolute_import, print_function

import os
from functools import wraps

from .compat import PY2, text_to_native_os_str, native_os_str_to_text, u


__all__ = []


_MARKER = object()


def _envlookup(name, default=_MARKER):
    """Lookup an environment variable"""
    try:
        return native_os_str_to_text(os.environ[name])
    except KeyError:
        if default is _MARKER:
            raise
        else:
            return default


def _oslookup(name, default=_MARKER):
    """Lookup some process and/or OS state """
    if name == "cwd":
        return native_os_str_to_text(os.getcwd())
    raise KeyError("key %r not found in the namespace" % name)


def _pylookup(name, default=_MARKER):
    """Lookup Python specific information"""
    import platform
    if name == "version":
        return u(platform.python_version())
    elif name == "implementation":
        return  u(platform.python_implementation())
    elif name == "version_maj_min":
        t = platform.python_version_tuple()
        return u('.'.join(t[:2]))
    elif name == "version_maj":
        t = platform.python_version_tuple()
        return u(t[0])
    else:
        if default is _MARKER:
            raise KeyError("variable %r not found in namespace PY" % name)
        else:
            return default


_varns_registry = {
    "ENV": _envlookup,
    "OS": _oslookup,
    "PY": _pylookup
}


def lookup_varns(name):
    return _varns_registry[_normalized(name)]


_filter_registry = {}


def add_filter(name, fn):
    """Register a variable filter with name `name` and implementation `fn`

    """
    _filter_registry[_normalized(name)] = fn


def lookup_filter(name):
    """Lookup a variable filter with name `name` and return it's implementation
    function

    """
    return _filter_registry[_normalized(name)]


def filter(name):
    """Decorator for a filter function.

    Example usage::

       @filter("myfilter")
       def myfilter_impl(appconfig, variable_value):
           filtered_value = ...
           return filtered_value


    """

    def _decorator(f):

        @wraps(f)
        def _f(appconfig, v):
            return f(appconfig, v)

        add_filter(name, _f)
        return _f

    return _decorator


def _normalized(name):
    return name.replace('-', '_')


#
# Some pre-defined filter functions
#
if PY2:

    @filter("urlquote")
    def urlquote(config, v):
        """Filter function to replace all special characters in string using
        the ``%xx`` escape

        """
        from urllib import quote
        return quote(v.encode("utf-8"), safe=b"").decode("utf-8")

else:

    @filter("urlquote")
    def urlquote(config, v):
        """Filter function to replace all special characters in string using
        the ``%xx`` escape

        """
        from urllib.parse import quote
        return quote(v, safe="")


@filter("saslprep")
def saslprep(config, v):
    """Filter function to perform a `SASLprep` according to :rfc:`4013` on
    `v`.

    This is a Stringprep Profile for usernames and passwords

    """
    import passlib.utils
    return passlib.utils.saslprep(v)


@filter("normpath")
def normpath_impl(config, v):
    """Implementation of the `normpath` filter function"""
    return os.path.normpath(v)


@filter("abspath")
def abspath_impl(config, v):
    """Implementation of the `abspath` filter function"""
    return os.path.abspath(v)


@filter("posixpath")
def posixpath_impl(config, v):
    """Implementation of the `posixpath` filter function"""
    return v.replace(u('\\'), u('/'))


@filter("lower")
def lower_impl(config, v):
    """Implementation of the `lower` filter function"""
    return v.lower()


@filter("upper")
def upper_impl(config, v):
    """Implementation of the `upper` filter function"""
    return v.upper()
