#
# Copyright (c) Daniel Sheffield 2023
#
# All rights reserved
#
# THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
from bottle import FormsDict
from pytest import fixture, mark, raises
from app.rest import PARAMS
from app.rest.route_decorators import (
    normalize,
    cursor,
    normalize_query,
    poison,
)

def incr(_dict, key):
    _dict[key] = _dict[key] + 1

@fixture
def counter():
    return dict()

@fixture
def tracker():
    return dict()

@fixture
def method(counter, tracker):
    counter['method'] = 0
    tracker['method'] = []
    return lambda *args, **kwargs: incr(counter, 'method') or \
        tracker['method'].push({'args': args, 'kwargs': kwargs})

@mark.parametrize('form_data, expected', [
    ([
        ('product', 'kiwi'),
        ('product', 'apple'),
        ('organic', ''),
    ], 'category=&group=&organic=0.5&product=apple%7Ckiwi&tag=&unit='),
    ([
        ('product', 'kiwi'),
        ('category', '!baking'),
        ('organic', '1'),
    ], 'category=%21baking&group=&organic=1&product=kiwi&tag=&unit='),
])
def test_normalise_query(form_data, expected):
    form = FormsDict()
    for k,v in form_data:
        form.append(k, v)
    
    assert normalize_query(form, allow=PARAMS) == expected

# need to mock bottle request.params
def test_normalize(counter, tracker, method):
    decorated = normalize(method)
    assert callable(decorated)
    #decorated()
    #assert counter['method'] == 1
    #assert tracker['method'][0]['args'] == []
    #assert tracker['method'][0]['kwargs'] == {'allow': None}
    decorated = normalize(method, allow=PARAMS)
    assert callable(decorated)
    #assert counter['method'] == 2
    #assert tracker['method'][1]['args'] == []
    #assert tracker['method'][1]['kwargs'] == {'allow': None}

def test_poison(counter, tracker, method):
    decorated = poison(cache=None)
    assert callable(decorated)
    #decorated()
    #assert counter['method'] == 1
    #assert tracker['method'][0]['args'] == []
    #assert tracker['method'][0]['kwargs'] == {'allow': None}
    with raises(Exception) as ex:
        poison(method)
    assert ex.value.args[0] == "decorator argument required"

def test_cursor(counter, tracker, method):
    decorated = cursor(cache=None)
    assert callable(decorated)
    #decorated()
    #assert counter['method'] == 1
    #assert tracker['method'][0]['args'] == []
    #assert tracker['method'][0]['kwargs'] == {'allow': None}
    with raises(Exception) as ex:
        cursor(method)
    assert ex.value.args[0] == "decorator argument required"
