from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.utils.translation import gettext as _

from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.parsers import JSONParser
from rest_framework.response import Response

from misago.acl import add_acl
from misago.categories.models import CATEGORIES_TREE_ID, Category
from misago.categories.permissions import (
    allow_see_category, allow_browse_category)
from misago.core.shortcuts import get_int_or_404, get_object_or_404
from misago.readtracker.categoriestracker import read_category
from misago.users.rest_permissions import IsAuthenticatedOrReadOnly

from misago.threads.api.threadendpoints.lists import threads_list_endpoint
from misago.threads.api.threadendpoints.merge import threads_merge_endpoint
from misago.threads.api.threadendpoints.patch import thread_patch_endpoint
from misago.threads.models import Thread, Subscription
from misago.threads.moderation import threads as moderation
from misago.threads.permissions.threads import allow_see_thread
from misago.threads.serializers import ThreadSerializer
from misago.threads.subscriptions import make_subscription_aware


class ThreadViewSet(viewsets.ViewSet):
    permission_classes = (IsAuthenticatedOrReadOnly, )
    parser_classes=(JSONParser, )

    TREE_ID = CATEGORIES_TREE_ID

    def validate_thread_visible(self, user, thread):
        allow_see_thread(user, thread)

    def get_thread(self, user, thread_id):
        thread = get_object_or_404(Thread.objects.select_related('category'),
            id=get_int_or_404(thread_id),
            category__tree_id=self.TREE_ID,
        )

        add_acl(user, thread.category)
        add_acl(user, thread)

        self.validate_thread_visible(user, thread)

        return thread

    def list(self, request):
        return threads_list_endpoint(request)

    def retrieve(self, request, pk=None):
        thread = self.get_thread(request.user, pk)
        make_subscription_aware(request.user, thread)
        return Response(ThreadSerializer(thread).data)

    def partial_update(self, request, pk=None):
        thread = self.get_thread(request.user, pk)
        return thread_patch_endpoint.dispatch(request, thread)

    def destroy(self, request, pk=None):
        thread = self.get_thread(request.user, pk)

        if thread.acl.get('can_hide') == 2:
            moderation.delete_thread(request.user, thread)
            return Response({'detail': 'ok'})
        else:
            raise PermissionDenied(
                _("You don't have permission to delete this thread."))

    @list_route(methods=['post'])
    def read(self, request):
        if request.query_params.get('category'):
            category_id = get_int_or_404(request.query_params.get('category'))
            category = get_object_or_404(Category.objects,
                id=category_id,
                tree_id=self.TREE_ID,
            )

            allow_see_category(request.user, category)
            allow_browse_category(request.user, category)
        else:
            category = Category.objects.root_category()

        read_category(request.user, category)
        return Response({'detail': 'ok'})

    @list_route(methods=['post'])
    def merge(self, request):
        return threads_merge_endpoint(request)