# django
from django.views import View
from rest_framework.views import APIView
from rest_framework.response import Response
from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.contrib.auth.models import User
from django.http import JsonResponse
from django.core.exceptions import ValidationError

# rest
from rest_framework import serializers

# models
from .models import Vote

# tags
from .templatetags.vote import (
    is_vote, 
    upvote_count, 
    downvote_count
)

def get_content_type(app_label, model):
    return ContentType.objects.get(
        app_label=app_label, 
        model=model
    )

def get_model(app_label, model):
    content_type_obj = ContentType.objects.get(
        app_label=app_label, 
        model=model
    )
    return content_type_obj.model_class()


class DjangoVoteSerializer(serializers.ModelSerializer):
    username = serializers.ReadOnlyField(
        source="user.username"
    )
    class Meta:
        model = Vote
        fields = ("username", "status")
        read_only_fields = ["status"]


class VoteView(View):

    @method_decorator(login_required)
    def post(self, request, app_label, model, id):
        if request.POST.get("status") == "false":
            status = False
        elif request.POST.get("status") == "true":
            status = True
        try:
            Vote(
                user=self.request.user,
                content_type=get_content_type(app_label, model), 
                object_id=id,
                status=status
            ).save()
        except ValidationError as e:
            return HttpResponse(
                JsonResponse(
                    {
                        "error": str(e)
                    }
                )
            )
        model = get_model(app_label=app_label, model=model)
        return HttpResponse(
            JsonResponse(
                {
                    "status": is_vote(self.request.user, model, id),
                    "upvote_count": upvote_count(model, id),
                    "downvote_count": downvote_count(model, id),
                }
            )
        )


class GetVotes(APIView):
    
    serializer_class = DjangoVoteSerializer
    permission_classes = []

    def get(self, request, app_label, model, id):
        queryset = Vote.objects.filter(
            content_type=get_content_type(
                app_label, 
                model
            ), 
            object_id=id,
        )
        serializer = self.serializer_class(queryset, many=True)
        return Response(serializer.data)


class IsVote(View):

    def get(self, request, username, app_label, model, id):
        user = User.objects.get(username=username)
        model = get_model(
            app_label=app_label, 
            model=model
        )
        return HttpResponse(
            JsonResponse(
                {
                    "status": is_vote(user, model, id)
                }
            )
        )

# django
from django.views import View
from rest_framework.views import APIView
from rest_framework.response import Response
from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.contrib.auth.models import User
from django.http import JsonResponse
from django.core.exceptions import ValidationError

# rest
from rest_framework import serializers

# models
from .models import Vote

# tags
from .templatetags.vote import (
    is_vote, 
    upvote_count, 
    downvote_count
)

def get_content_type(app_label, model):
    return ContentType.objects.get(
        app_label=app_label, 
        model=model
    )

def get_model(app_label, model):
    content_type_obj = ContentType.objects.get(
        app_label=app_label, 
        model=model
    )
    return content_type_obj.model_class()


class DjangoVoteSerializer(serializers.ModelSerializer):
    username = serializers.ReadOnlyField(
        source="user.username"
    )
    class Meta:
        model = Vote
        fields = ("username", "status")
        read_only_fields = ["status"]


class VoteView(View):

    @method_decorator(login_required)
    def post(self, request, app_label, model, id):
        if request.POST.get("status") == "false":
            status = False
        elif request.POST.get("status") == "true":
            status = True
        try:
            Vote(
                user=self.request.user,
                content_type=get_content_type(app_label, model), 
                object_id=id,
                status=status
            ).save()
        except ValidationError as e:
            return HttpResponse(
                JsonResponse(
                    {
                        "error": str(e)
                    }
                )
            )
        model = get_model(app_label=app_label, model=model)
        return HttpResponse(
            JsonResponse(
                {
                    "status": is_vote(self.request.user, model, id),
                    "upvote_count": upvote_count(model, id),
                    "downvote_count": downvote_count(model, id),
                }
            )
        )


class GetVotes(APIView):
    
    serializer_class = DjangoVoteSerializer
    permission_classes = []

    def get(self, request, app_label, model, id):
        queryset = Vote.objects.filter(
            content_type=get_content_type(
                app_label, 
                model
            ), 
            object_id=id,
        )
        serializer = self.serializer_class(queryset, many=True)
        return Response(serializer.data)


class IsVote(View):

    def get(self, request, username, app_label, model, id):
        user = User.objects.get(username=username)
        model = get_model(
            app_label=app_label, 
            model=model
        )
        return HttpResponse(
            JsonResponse(
                {
                    "status": is_vote(user, model, id)
                }
            )
        )

# django # rest # models # tags