import operator

from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404

from rest_framework.permissions import BasePermission

from funkwhale_api.common import preferences


class ConditionalAuthentication(BasePermission):
    def has_permission(self, request, view):
        if preferences.get("common__api_authentication_required"):
            return (request.user and request.user.is_authenticated) or (
                hasattr(request, "actor") and request.actor
            )
        return True


class OwnerPermission(BasePermission):
    """
    Ensure the request user is the owner of the object.

    Usage:

    class MyView(APIView):
        model = MyModel
        permission_classes = [OwnerPermission]
        owner_field = 'owner'
        owner_checks = ['read', 'write']
    """

    perms_map = {
        "GET": "read",
        "OPTIONS": "read",
        "HEAD": "read",
        "POST": "write",
        "PUT": "write",
        "PATCH": "write",
        "DELETE": "write",
    }

    def has_object_permission(self, request, view, obj):
        method_check = self.perms_map[request.method]
        owner_checks = getattr(view, "owner_checks", ["read", "write"])
        if method_check not in owner_checks:
            # check not enabled
            return True

        owner_field = getattr(view, "owner_field", "user")
        owner_exception = getattr(view, "owner_exception", Http404)
        try:
            owner = operator.attrgetter(owner_field)(obj)
        except ObjectDoesNotExist:
            raise owner_exception

        if not owner or not request.user.is_authenticated or owner != request.user:
            raise owner_exception
        return True
