from django.http import HttpResponse
import json

"""
Handle ajax calls.
The decorator, register_ajax, creates an entry in the dispatcher
dictionary. Only ajax calls listed in the dispatcher will be run.
To handle optional arguments that specify restrictions on who can
run this ajax call, optional keyword arguments may be supplied to
the decorator.

The decorator extracts the module and name of the function object
passed in, which it uses to compute the name it expects to be passed
from Javascript. The js code in mysrc/base.html handles merging the
'ajax' argument supplied in the rendering dictionary with the url
argument supplied to the call_ajax javascript call to generate the
appropriate matching key value in the dispatcher database.

Example:

In the django app 'mpl', a view that enables ajax will pass in its
rendering dictionary the item 'ajax': 'mpl'. Suppose that a function
fred(request) in file views.py of module mpl is registered with
the register_ajax decorator. Within the html template
for the page to be rendered, call ajax_call('views.fred', args, callback).

@register()
def theview(request, args):
    '''Make sure to return a dictionary of return values or throw
    an error.
    '''
"""

dispatcher = dict()


def register_ajax(*args, **kwargs):
    def handler(f):
        d = dict(f=f, name=f.__name__, module=f.__module__, restrictions=None)
        if 'restrictions' in kwargs:
            d['restrictions'] = kwargs['restrictions']
        dispatcher[f"{d['module']}.{d['name']}"] = d

        return f

    return handler


def ajax(request):
    """Handle an ajax request"""

    CT = "application/x-www-form-urlencoded; charset=UTF-8"
    is_ajax = request.META.get("CONTENT_TYPE") == CT
    if is_ajax and request.method == 'POST':
        args = dict()
        for k, v in request.POST.items():
            args[k] = v[0] if (isinstance(v, list) and len(v) == 1) else v

        setattr(request, 'cleaned_data', args)
        command = args['url']

        try:
            f = dispatcher[command]
            restrictions = f['restrictions']
            if restrictions:
                print(restrictions)
            res = f['f'](request, args)
        except Exception as eeps:
            res = request.cleaned_data
            res['exception'] = str(eeps)
        return HttpResponse(json.dumps(res))
    return HttpResponse(json.dumps(dict(ct=request.META.get("CONTENT_TYPE"))))
