# -*- coding: utf-8 -*-

import datetime
import pytest
import string

from django.test import override_settings
from quixote import cleanup
from wcs.qommon.substitution import CompatibilityNamesDict
from wcs.qommon.template import Template, TemplateError
from wcs.conditions import Condition
from wcs.variables import LazyFormData

from utilities import create_temporary_pub, clean_temporary_pub


def setup_module(module):
    cleanup()
    global pub
    pub = create_temporary_pub()
    pub.substitutions.feed(pub)


def teardown_module(module):
    clean_temporary_pub()


def test_template():
    tmpl = Template('')
    assert tmpl.render() == ''
    assert tmpl.render({'foo': 'bar'}) == ''
    tmpl = Template('zoo')
    assert tmpl.render() == 'zoo'
    assert tmpl.render({'foo': 'bar'}) == 'zoo'

    # django
    tmpl = Template('{{ foo }}')
    assert tmpl.render() == ''
    assert tmpl.render({'foo': 'bar'}) == 'bar'
    tmpl = Template('{% if foo %}{{ foo }}{% endif %}')
    assert tmpl.render() == ''
    assert tmpl.render({'foo': 'bar'}) == 'bar'

    # ezt
    tmpl = Template('[foo]')
    assert tmpl.render() == '[foo]'
    assert tmpl.render({'foo': 'bar'}) == 'bar'
    tmpl = Template('[if-any foo][foo][end]')
    assert tmpl.render() == ''
    assert tmpl.render({'foo': 'bar'}) == 'bar'

    # mix Django/ezt: Django wins
    tmpl = Template('{% if foo %}{{ foo }}[foo]{% endif %}')
    assert tmpl.render({'foo': 'bar'}) == 'bar[foo]'

    # django syntax error
    with pytest.raises(TemplateError):
        tmpl = Template('{% if foo %}{{ foo }}{% end %}', raises=True)
    tmpl = Template('{% if foo %}{{ foo }}{% end %}')
    assert tmpl.render({'foo': 'bar'}) == '{% if foo %}{{ foo }}{% end %}'

    # ezt syntax error
    with pytest.raises(TemplateError):
        tmpl = Template('[if-any foo][foo][endif]', raises=True)
    tmpl = Template('[if-any foo][foo][endif]')
    assert tmpl.render({'foo': 'bar'}) == '[if-any foo][foo][endif]'

def test_now_and_today_variables():
    # create a today string, verify it contains the year, at least
    today = Template('{{d}}').render({'d': datetime.date.today()})
    assert datetime.date.today().strftime('%Y') in today

    tmpl = Template('{{ today }}')
    for mode in (None, 'lazy'):
        context = pub.substitutions.get_context_variables(mode=mode)
        assert tmpl.render(context) == today
    tmpl = Template('{{ now }}')
    for mode in (None, 'lazy'):
        context = pub.substitutions.get_context_variables(mode=mode)
        assert today in tmpl.render(context)  # contains the date,
        assert tmpl.render(context) != today  # but not only

    # ezt templates (legacy)
    today = Template('[t]').render({'t': datetime.date.today()})
    assert today == datetime.date.today().strftime('%Y-%m-%d')
    now = Template('[n]').render({'n': datetime.datetime.now()})
    assert now == datetime.datetime.now().strftime('%Y-%m-%d %H:%M')

    tmpl = Template('[today]')
    for mode in (None, 'lazy'):
        context = pub.substitutions.get_context_variables(mode=mode)
        assert tmpl.render(context) == today
    tmpl = Template('[now]')
    for mode in (None, 'lazy'):
        context = pub.substitutions.get_context_variables(mode=mode)
        assert tmpl.render(context) == now

def test_template_templatetag():
    # check qommon templatetags are always loaded
    tmpl = Template('{{ date|parse_datetime|date:"Y" }}')
    assert tmpl.render({'date': '2018-06-06'}) == '2018'

    # check other templatetags can be loaded
    tmpl = Template('{% load i18n %}{% trans "hello" %}')
    assert tmpl.render() == 'hello'

def test_startswith_templatetag():
    tmpl = Template('{% if foo|startswith:"bar" %}hello{% endif %}')
    assert tmpl.render() == ''
    assert tmpl.render({'foo': 'bar-baz'}) == 'hello'
    assert tmpl.render({'foo': 'baz-bar'}) == ''

def test_split_templatetag():
    tmpl = Template('{{ foo|split|last }}')
    assert tmpl.render() == ''
    assert tmpl.render({'foo': 'bar baz'}) == 'baz'
    assert tmpl.render({'foo': 'baz-bar'}) == 'baz-bar'

    tmpl = Template('{{ foo|split:"-"|last }}')
    assert tmpl.render() == ''
    assert tmpl.render({'foo': 'bar-baz'}) == 'baz'
    assert tmpl.render({'foo': 'baz-bar'}) == 'bar'

def test_strip_templatetag():
    tmpl = Template('{{ foo|strip }}')
    assert tmpl.render() == ''
    assert tmpl.render({'foo': None}) == ''
    assert tmpl.render({'foo': ' foo bar '}) == 'foo bar'
    assert tmpl.render({'foo': ' foo bar\t'}) == 'foo bar'
    assert tmpl.render({'foo': ' félé  '}) == 'félé'
    tmpl = Template('{{ foo|strip:"XY" }}')
    assert tmpl.render({'foo': 'XXfoo barXYX'}) == 'foo bar'
    assert tmpl.render({'foo': ' foo barXX'}) == ' foo bar'

def test_template_encoding():
    # django
    tmpl = Template('{{ foo }} à vélo')
    assert tmpl.render() == ' à vélo'
    assert tmpl.render({'foo': 'fou'}) == 'fou à vélo'
    assert tmpl.render({'foo': 'félé'}) == 'félé à vélo'

    tmpl = Template("{% if foo == 'félé' %}à vélo{% endif %}")
    assert tmpl.render() == ''
    assert tmpl.render({'foo': 'fou'}) == ''
    assert tmpl.render({'foo': 'félé'}) == 'à vélo'

    tmpl = Template("{% if foo.bar == 'félé' %}à vélo{% endif %}")
    assert tmpl.render() == ''
    assert tmpl.render({'foo': {'bar': 'fou'}}) == ''
    assert tmpl.render({'foo': {'bar': 'félé'}}) == 'à vélo'

    # ezt
    tmpl = Template('[foo] à vélo')
    assert tmpl.render() == '[foo] à vélo'
    assert tmpl.render({'foo': 'fou'}) == 'fou à vélo'
    assert tmpl.render({'foo': 'félé'}) == 'félé à vélo'


def test_datetime_templatetags():
    tmpl = Template('{{ plop|datetime }}')
    assert tmpl.render({'plop': '2017-12-21 10:32'}) == '2017-12-21 10:32'
    assert tmpl.render({'plop': '21/12/2017 10h32'}) == '2017-12-21 10:32'
    assert tmpl.render({'plop': '2017-12-21'}) == '2017-12-21 00:00'
    assert tmpl.render({'plop': '21/12/2017'}) == '2017-12-21 00:00'
    with override_settings(LANGUAGE_CODE='fr-fr'):
        assert tmpl.render({'plop': '2017-12-21 10:32'}) == '21/12/2017 10:32'
        assert tmpl.render({'plop': '21/12/2017 10h32'}) == '21/12/2017 10:32'
        assert tmpl.render({'plop': '2017-12-21'}) == '21/12/2017 00:00'
        assert tmpl.render({'plop': '21/12/2017'}) == '21/12/2017 00:00'
    assert tmpl.render({'plop': '10h32'}) == ''
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

    tmpl = Template('{{ plop|datetime:"d i" }}')
    assert tmpl.render({'plop': '2017-12-21 10:32'}) == '21 32'
    assert tmpl.render({'plop': '2017-12-21 10:32:42'}) == '21 32'
    assert tmpl.render({'plop': '21/12/2017 10:32'}) == '21 32'
    assert tmpl.render({'plop': '21/12/2017 10:32:42'}) == '21 32'
    assert tmpl.render({'plop': '21/12/2017 10h32'}) == '21 32'
    assert tmpl.render({'plop': '21/12/2017'}) == '21 00'
    assert tmpl.render({'plop': '10h32'}) == ''
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

    tmpl = Template('{% if d1|datetime > d2|datetime %}d1>d2{% else %}d1<=d2{% endif %}')
    assert tmpl.render({'d1': '2017-12-22', 'd2': '2017-12-21'}) == 'd1>d2'
    assert tmpl.render({'d1': '2017-12-21', 'd2': '2017-12-21'}) == 'd1<=d2'
    assert tmpl.render({'d1': '2017-12-21 10:30', 'd2': '2017-12-21 09:00'}) == 'd1>d2'
    assert tmpl.render({'d1': '2017-12-21 10:30', 'd2': '2017-12-21'}) == 'd1>d2'
    assert tmpl.render({'d1': '2017-12-22'}) == 'd1<=d2'
    assert tmpl.render({'d2': '2017-12-22'}) == 'd1<=d2'

    tmpl = Template('{{ plop|date }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '2017-12-21'
    assert tmpl.render({'plop': '21/12/2017'}) == '2017-12-21'
    assert tmpl.render({'plop': '2017-12-21 10:32'}) == '2017-12-21'
    assert tmpl.render({'plop': '21/12/2017 10:32'}) == '2017-12-21'
    assert tmpl.render({'plop': '21/12/2017 10h32'}) == '2017-12-21'
    assert tmpl.render({'plop': '21/12/2017 10:32:42'}) == '2017-12-21'
    with override_settings(LANGUAGE_CODE='fr-fr'):
        assert tmpl.render({'plop': '2017-12-21'}) == '21/12/2017'
        assert tmpl.render({'plop': '21/12/2017'}) == '21/12/2017'
        assert tmpl.render({'plop': '2017-12-21 10:32'}) == '21/12/2017'
        assert tmpl.render({'plop': '21/12/2017 10:32'}) == '21/12/2017'
        assert tmpl.render({'plop': '21/12/2017 10h32'}) == '21/12/2017'
        assert tmpl.render({'plop': '21/12/2017 10:32:42'}) == '21/12/2017'
    assert tmpl.render({'plop': '10:32'}) == ''
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

    tmpl = Template('{{ plop|date:"d" }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '21'
    assert tmpl.render({'plop': '21/12/2017'}) == '21'
    assert tmpl.render({'plop': '2017-12-21 10:32'}) == '21'
    assert tmpl.render({'plop': '10:32'}) == ''
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

    tmpl = Template('{% if d1|date > d2|date %}d1>d2{% else %}d1<=d2{% endif %}')
    assert tmpl.render({'d1': '2017-12-22', 'd2': '2017-12-21'}) == 'd1>d2'
    assert tmpl.render({'d1': '2017-12-21', 'd2': '2017-12-21'}) == 'd1<=d2'
    assert tmpl.render({'d1': '2017-12-22'}) == 'd1<=d2'
    assert tmpl.render({'d2': '2017-12-22'}) == 'd1<=d2'

    tmpl = Template('{{ plop|time }}')
    assert tmpl.render({'plop': '10:32'}) == '10:32 a.m.'
    assert tmpl.render({'plop': '2017-12-21 10:32'}) == '10:32 a.m.'
    assert tmpl.render({'plop': '21/12/2017 10h32'}) == '10:32 a.m.'
    assert tmpl.render({'plop': '21/12/2017'}) == 'midnight'
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

    tmpl = Template('{{ plop|time:"H i" }}')
    assert tmpl.render({'plop': '10:32'}) == '10 32'
    assert tmpl.render({'plop': '2017-12-21 10:32'}) == '10 32'
    assert tmpl.render({'plop': '21/12/2017 10h32'}) == '10 32'
    assert tmpl.render({'plop': '21/12/2017'}) == '00 00'
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

    # old fashion, with parse_*
    tmpl = Template('{{ plop|parse_datetime|date:"d i" }}')
    assert tmpl.render({'plop': '2017-12-21 10:32'}) == '21 32'
    assert tmpl.render({'plop': '2017-12-21 10:32:42'}) == '21 32'
    assert tmpl.render({'plop': '21/12/2017 10:32'}) == '21 32'
    assert tmpl.render({'plop': '21/12/2017 10:32:42'}) == '21 32'
    assert tmpl.render({'plop': '21/12/2017 10h32'}) == '21 32'
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

    tmpl = Template('{{ plop|parse_date|date:"d" }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '21'
    assert tmpl.render({'plop': '21/12/2017'}) == '21'
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

    tmpl = Template('{{ plop|parse_time|date:"H i" }}')
    assert tmpl.render({'plop': '10:32'}) == '10 32'
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 3}) == ''
    assert tmpl.render({'plop': {'foo': 'bar'}}) == ''
    assert tmpl.render() == ''

def test_date_maths():
    tmpl = Template('{{ plop|add_days:4 }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '2017-12-25'
    assert tmpl.render({'plop': '2017-12-21 18:00'}) == '2017-12-25'
    tmpl = Template('{{ plop|add_days:"-1" }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '2017-12-20'
    assert tmpl.render({'plop': '2017-12-21 18:00'}) == '2017-12-20'
    tmpl = Template('{{ plop|add_days:1.5 }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '2017-12-22'
    assert tmpl.render({'plop': '2017-12-21 18:00'}) == '2017-12-22'
    tmpl = Template('{{ plop|add_days:"1.5" }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '2017-12-22'
    assert tmpl.render({'plop': '2017-12-21 18:00'}) == '2017-12-22'

    tmpl = Template('{{ plop|add_hours:24 }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '2017-12-22 00:00'
    assert tmpl.render({'plop': '2017-12-21 18:00'}) == '2017-12-22 18:00'
    tmpl = Template('{{ plop|add_hours:"12.5" }}')
    assert tmpl.render({'plop': '2017-12-21'}) == '2017-12-21 12:30'
    assert tmpl.render({'plop': '2017-12-21 18:00'}) == '2017-12-22 06:30'

def test_variable_unicode_error_handling():
    tmpl = Template('{{ form_var_éléphant }}')
    assert tmpl.render() == ''

def test_decimal_templatetag():
    tmpl = Template('{{ plop|decimal }}')
    assert tmpl.render({'plop': 'toto'}) == '0'
    assert tmpl.render({'plop': '3.14'}) == '3.14'
    assert tmpl.render({'plop': '3,14'}) == '3.14'
    assert tmpl.render({'plop': 3.14}) == '3.14'
    assert tmpl.render({'plop': 12345.678}) == '12345.678'
    assert tmpl.render({'plop': None}) == '0'
    assert tmpl.render({'plop': 0}) == '0'

    tmpl = Template('{{ plop|decimal:3 }}')
    assert tmpl.render({'plop': '3.14'}) == '3.140'
    assert tmpl.render({'plop': None}) == '0.000'
    tmpl = Template('{{ plop|decimal:"3" }}')
    assert tmpl.render({'plop': '3.14'}) == '3.140'
    assert tmpl.render({'plop': None}) == '0.000'

    tmpl = Template('{% if plop|decimal > 2 %}hello{% endif %}')
    assert tmpl.render({'plop': 3}) == 'hello'
    assert tmpl.render({'plop': '3'}) == 'hello'
    assert tmpl.render({'plop': 2.001}) == 'hello'
    assert tmpl.render({'plop': '2.001'}) == 'hello'
    assert tmpl.render({'plop': 1}) == ''
    assert tmpl.render({'plop': 1.99}) == ''
    assert tmpl.render({'plop': '1.99'}) == ''
    assert tmpl.render({'plop': 'x'}) == ''
    assert tmpl.render({'plop': None}) == ''
    assert tmpl.render({'plop': 0}) == ''

    tmpl = Template('{% if "3"|decimal == 3 %}hello{% endif %}')
    assert tmpl.render() == 'hello'
    tmpl = Template('{% if "3"|decimal == 3.0 %}hello{% endif %}')
    assert tmpl.render() == 'hello'
    tmpl = Template('{% if 3|decimal == 3 %}hello{% endif %}')
    assert tmpl.render() == 'hello'
    tmpl = Template('{% if 3.0|decimal == 3 %}hello{% endif %}')
    assert tmpl.render() == 'hello'
    tmpl = Template('{% if 3|decimal|decimal == 3 %}hello{% endif %}')
    assert tmpl.render() == 'hello'

def test_mathematics_templatetag():
    tmpl = Template('{{ term1|add:term2 }}')

    # using string: convert to number or 0
    assert tmpl.render({'term1': '1.1', 'term2': 0}) == '1.1'
    assert tmpl.render({'term1': 'not a number', 'term2': 1.2}) == '1.2'
    assert tmpl.render({'term1': 0.3, 'term2': "1"}) == '1.3'
    assert tmpl.render({'term1': 1.4, 'term2': "not a number"}) == '1.4'

    # add
    assert tmpl.render({'term1': 4, 'term2': -0.9}) == '3.1'
    assert tmpl.render({'term1': '4', 'term2': -0.8}) == '3.2'
    assert tmpl.render({'term1': 4, 'term2': '-0.7'}) == '3.3'
    assert tmpl.render({'term1': '4', 'term2': '-0.6'}) == '3.4'
    assert tmpl.render({'term1': '', 'term2': 3.5}) == '3.5'
    assert tmpl.render({'term1': 3.6, 'term2': ''}) == '3.6'
    assert tmpl.render({'term1': '', 'term2': ''}) == '0'
    assert tmpl.render({'term1': 0, 'term2': ''}) == '0'
    assert tmpl.render({'term1': '', 'term2': 0}) == '0'
    assert tmpl.render({'term1': 0, 'term2': 0}) == '0'

    # subtract
    tmpl = Template('{{ term1|subtract:term2 }}')
    assert tmpl.render({'term1': 5.1, 'term2': 1}) == '4.1'
    assert tmpl.render({'term1': '5.2', 'term2': 1}) == '4.2'
    assert tmpl.render({'term1': 5.3, 'term2': '1'}) == '4.3'
    assert tmpl.render({'term1': '5.4', 'term2': '1'}) == '4.4'
    assert tmpl.render({'term1': '', 'term2': -4.5}) == '4.5'
    assert tmpl.render({'term1': 4.6, 'term2': ''}) == '4.6'
    assert tmpl.render({'term1': '', 'term2': ''}) == '0'
    assert tmpl.render({'term1': 0, 'term2': ''}) == '0'
    assert tmpl.render({'term1': '', 'term2': 0}) == '0'
    assert tmpl.render({'term1': 0, 'term2': 0}) == '0'

    # multiply
    tmpl = Template('{{ term1|multiply:term2 }}')
    assert tmpl.render({'term1': '3', 'term2': '2'}) == '6'
    assert tmpl.render({'term1': 2.5, 'term2': 2}) == '5.0'
    assert tmpl.render({'term1': '2.5', 'term2': 2}) == '5.0'
    assert tmpl.render({'term1': 2.5, 'term2': '2'}) == '5.0'
    assert tmpl.render({'term1': '2.5', 'term2': '2'}) == '5.0'
    assert tmpl.render({'term1': '', 'term2': '2'}) == '0'
    assert tmpl.render({'term1': 2.5, 'term2': ''}) == '0.0'
    assert tmpl.render({'term1': '', 'term2': ''}) == '0'
    assert tmpl.render({'term1': 0, 'term2': ''}) == '0'
    assert tmpl.render({'term1': '', 'term2': 0}) == '0'
    assert tmpl.render({'term1': 0, 'term2': 0}) == '0'

    # divide
    tmpl = Template('{{ term1|divide:term2 }}')
    assert tmpl.render({'term1': 16, 'term2': 2}) == '8'
    assert tmpl.render({'term1': 6, 'term2': 0.75}) == '8'
    assert tmpl.render({'term1': '6', 'term2': 0.75}) == '8'
    assert tmpl.render({'term1': 6, 'term2': '0.75'}) == '8'
    assert tmpl.render({'term1': '6', 'term2': '0.75'}) == '8'
    assert tmpl.render({'term1': '', 'term2': '2'}) == '0'
    assert tmpl.render({'term1': 6, 'term2': ''}) == ''
    assert tmpl.render({'term1': '', 'term2': ''}) == ''
    assert tmpl.render({'term1': 0, 'term2': ''}) == ''
    assert tmpl.render({'term1': '', 'term2': 0}) == ''
    assert tmpl.render({'term1': 0, 'term2': 0}) == ''
    tmpl = Template('{{ term1|divide:term2|decimal:2 }}')
    assert tmpl.render({'term1': 2, 'term2': 3}) == '0.67'

def test_rounding_templatetag():
    # ceil
    tmpl = Template('{{ value|ceil }}')
    assert tmpl.render({'value': 3.14}) == '4'
    assert tmpl.render({'value': 3.99}) == '4'
    assert tmpl.render({'value': -3.14}) == '-3'
    assert tmpl.render({'value': -3.99}) == '-3'
    assert tmpl.render({'value': 0}) == '0'
    assert tmpl.render({'value': '3.14'}) == '4'
    assert tmpl.render({'value': '3.99'}) == '4'
    assert tmpl.render({'value': '-3.14'}) == '-3'
    assert tmpl.render({'value': '-3.99'}) == '-3'
    assert tmpl.render({'value': '0'}) == '0'
    assert tmpl.render({'value': 'not a number'}) == '0'
    assert tmpl.render({'value': ''}) == '0'
    assert tmpl.render({'value': None}) == '0'

    # floor
    tmpl = Template('{{ value|floor }}')
    assert tmpl.render({'value': 3.14}) == '3'
    assert tmpl.render({'value': 3.99}) == '3'
    assert tmpl.render({'value': -3.14}) == '-4'
    assert tmpl.render({'value': -3.99}) == '-4'
    assert tmpl.render({'value': 0}) == '0'
    assert tmpl.render({'value': '3.14'}) == '3'
    assert tmpl.render({'value': '3.99'}) == '3'
    assert tmpl.render({'value': '-3.14'}) == '-4'
    assert tmpl.render({'value': '-3.99'}) == '-4'
    assert tmpl.render({'value': '0'}) == '0'
    assert tmpl.render({'value': 'not a number'}) == '0'
    assert tmpl.render({'value': ''}) == '0'
    assert tmpl.render({'value': None}) == '0'

def test_abs_templatetag():
    tmpl = Template('{{ value|abs }}')
    assert tmpl.render({'value': 3.14}) == '3.14'
    assert tmpl.render({'value': -3.14}) == '3.14'
    assert tmpl.render({'value': 0}) == '0'
    assert tmpl.render({'value': '3.14'}) == '3.14'
    assert tmpl.render({'value': '-3.14'}) == '3.14'
    assert tmpl.render({'value': '0'}) == '0'
    assert tmpl.render({'value': 'not a number'}) == '0'
    assert tmpl.render({'value': ''}) == '0'
    assert tmpl.render({'value': None}) == '0'


def test_token_decimal():
    tokens = [Template('{% token_decimal 4 %}').render() for i in range(100)]
    assert all(len(token) == 4 for token in tokens)
    assert all(token.isdigit() for token in tokens)
    # check randomness, i.e. duplicates are rare
    assert len(set(tokens)) > 70
    t = Template('{% if token1|token_check:token2 %}ok{% endif %}')
    assert t.render({'token1': tokens[0] + ' ', 'token2': tokens[0].lower()}) == 'ok'
    t = Template('{% if "é"|token_check:"è" %}ok{% endif %}')
    assert t.render({'token1': tokens[0] + ' ', 'token2': tokens[0].lower()}) == ''


def test_token_alphanum():
    tokens = [Template('{% token_alphanum 4 %}').render() for i in range(100)]
    assert all(len(token) == 4 for token in tokens)
    assert all(token.upper() == token for token in tokens)
    assert all(token.isalnum() for token in tokens)
    # check randomness, i.e. duplicates are rare
    assert len(set(tokens)) > 90
    # check there are letters and digits
    assert any(set(token) & set(string.ascii_uppercase) for token in tokens)
    assert any(set(token) & set(string.digits) for token in tokens)
    # no look-alike characters
    assert not any(set(token) & set('01IiOo') for token in tokens)
    t = Template('{% if token1|token_check:token2 %}ok{% endif %}')
    assert t.render({'token1': tokens[0] + ' ', 'token2': tokens[0].lower()}) == 'ok'

def test_distance():
    t = Template('{{ "48;2"|distance:"48.1;2.1"|floatformat }}',)
    assert t.render() == '13387.2'
    t = Template('{{ coords|distance:"48.1;2.1"|floatformat }}',)
    assert t.render({'coords': '48;2'}) == '13387.2'
    t = Template('{{ "48;2"|distance:coords|floatformat }}',)
    assert t.render({'coords': '48.1;2.1'}) == '13387.2'
    t = Template('{{ c1|distance:c2|floatformat }}',)
    assert t.render({'c1': '48;2', 'c2': '48.1;2.1'}) == '13387.2'

    class MockFormData(object):
        formdef = None
        geolocations = {'base': {'lat': 48, 'lon': 2}}

    lazy_formdata = LazyFormData(MockFormData())
    for tpl in ('{{ formdata|distance:coords|floatformat }}',
                '{{ coords|distance:formdata|floatformat }}'):
        t = Template(tpl,)
        assert t.render({'formdata': lazy_formdata, 'coords': '48.1;2.1'}) == '13387.2'
        assert t.render({'formdata': lazy_formdata, 'coords': '49.1;3.1'}) == '146821.9'
        assert t.render({'formdata': lazy_formdata, 'coords': 'abc;def'}) == ''
        assert t.render({'formdata': lazy_formdata, 'coords': '42'}) == ''
        assert t.render({'formdata': lazy_formdata, 'coords': ''}) == ''
    MockFormData.geolocations = {}
    for tpl in ('{{ formdata|distance:coords|floatformat }}',
                '{{ coords|distance:formdata|floatformat }}'):
        t = Template(tpl,)
        assert t.render({'formdata': lazy_formdata, 'coords': '49.1;3.1'}) == ''

def test_get_filter():
    tmpl = Template('{{ foo|get:"bar" }}')
    assert tmpl.render({'foo': {'bar': 'baz'}}) == 'baz'

    tmpl = Template('{{ foo|get:0 }}')
    assert tmpl.render({'foo': ['bar', 'baz']}) == 'bar'

def test_reproj():

    class MockFormData(object):
        formdef = None
        geolocations = {'base': {'lat': 48, 'lon': 2}}

    lazy_formdata = LazyFormData(MockFormData())
    tmpl = Template('{% with form_geoloc_base|reproj:"EPSG:3946" as c %}{{c.0}}/{{c.1}}{% endwith %}')
    coords = tmpl.render(CompatibilityNamesDict({'form': lazy_formdata})).split('/')
    assert int(float(coords[0])) == 1625337
    assert int(float(coords[1])) == 5422836
