# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
# Copyright © 2018 Maël Kervella
#
# 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.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

"""api.utils.

Set of various and usefull functions for the API app
"""

from rest_framework.renderers import JSONRenderer
from django.http import HttpResponse


class JSONResponse(HttpResponse):
    """A JSON response that can be send as an HTTP response.
    Usefull in case of REST API.
    """

    def __init__(self, data, **kwargs):
        """Initialisz a JSONResponse object.

        Args:
            data: the data to render as JSON (often made of lists, dicts,
            strings, boolean and numbers). See `JSONRenderer.render(data)` for
            further details.

        Creates:
            An HTTPResponse containing the data in JSON format.
        """

        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)


class JSONError(JSONResponse):
    """A JSON response when the request failed.
    """

    def __init__(self, error_msg, data=None, **kwargs):
        """Initialise a JSONError object.

        Args:
            error_msg: A message explaining where the error is.
            data: An optional field for further data to send along.

        Creates:
            A JSONResponse containing a field `status` set to `error` and a
            field `reason` containing `error_msg`. If `data` argument has been
            given, a field `data` containing it is added to the JSON response.
        """

        response = {
            'status': 'error',
            'reason': error_msg
        }
        if data is not None:
            response['data'] = data
        super(JSONError, self).__init__(response, **kwargs)


class JSONSuccess(JSONResponse):
    """A JSON response when the request suceeded.
    """

    def __init__(self, data=None, **kwargs):
        """Initialise a JSONSucess object.

        Args:
            error_msg: A message explaining where the error is.
            data: An optional field for further data to send along.

        Creates:
            A JSONResponse containing a field `status` set to `sucess`. If
            `data` argument has been given, a field `data` containing it is
            added to the JSON response.
        """

        response = {
            'status': 'success',
        }
        if data is not None:
            response['data'] = data
        super(JSONSuccess, self).__init__(response, **kwargs)


def accept_method(methods):
    """Decorator to set a list of accepted request method.
    Check if the method used is accepted. If not, send a NotAllowed response.
    """

    def decorator(view):
        """The decorator to use on a specific view
        """
        def wrapper(request, *args, **kwargs):
            """The wrapper used for a specific request
            """
            if request.method in methods:
                return view(request, *args, **kwargs)
            else:
                return JSONError(
                    'Invalid request method. Request methods authorize are ' +
                    str(methods)
                )
            return view(request, *args, **kwargs)
        return wrapper
    return decorator