from django.shortcuts import HttpResponse, get_object_or_404, render, redirect
from django.views.generic import View, DetailView
from django.core.urlresolvers import reverse_lazy
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.conf import settings
from django.urls import reverse
from notifications.models import Notification
from iconolab.models import Collection, Annotation, IconolabComment, Image, MetaCategoriesCountInfo
from uuid import UUID
import logging

logger = logging.getLogger(__name__)

class UserHomeView(DetailView):
    model = User
    slug_field = 'id'

    def get_context_data(self, **kwargs):
        context = super(UserHomeView, self).get_context_data(**kwargs)
        return context

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data()
        profile_user = self.object
        context['profile_user'] = profile_user
        context['user_annotations'] = Annotation.objects.filter(author=profile_user).prefetch_related(
            'current_revision',
            'revisions',
            'image',
            'image__item',
            'image__item__collection'
        ).order_by("-created")[:5]
        context['user_contributed_annotations'] = Annotation.objects.get_annotations_contributed_for_user(profile_user)[:5]
        context['user_commented_annotations'] = Annotation.objects.get_annotations_commented_for_user(profile_user)[:5]
        # .exclude(annotation_guid__in=[annotation.annotation_guid for annotation in context['user_revisions_annotations']])
        
        if request.user.is_authenticated() and self.object == request.user:
            if request.GET.get('clear_notifications', False):
                Notification.objects.filter(recipient=request.user).mark_all_as_read()
            logger.debug(Notification.objects.filter(recipient=request.user))
            context['notifications'] = Notification.objects.filter(recipient=request.user)
        logger.debug(context)
        return render(request, 'iconolab/user_home.html', context)

class UserNotificationsView(View):

    def get(self, request, *args, **kwargs):
        context = {}
        notifications = Notification.objects.filter(recipient=request.user)
        context['notifications_unread_ids'] = notifications.unread().values_list('id', flat=True)
        page = request.GET.get('page', 1)
        paginator = Paginator(notifications, 50)
        try:
            notifications_list = paginator.page(page)
        except PageNotAnInteger:
            notifications_list = paginator.page(1)
        except EmptyPage:
            notifications_list = paginator.page(paginator.num_pages)
        context['notifications'] = notifications_list
        return render(request, 'iconolab/user_notifications.html', context)

class UserAnnotationsView(DetailView):
    model = User
    slug_field = 'id'
    
    def get_context_data(self, **kwargs):
        context = super(UserAnnotationsView, self).get_context_data(**kwargs)
        return context
    
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        profile_user = self.object
        context = self.get_context_data()
        page = request.GET.get('page', 1)
        per_page=request.GET.get('perpage', 10)
        paginator = Paginator(Annotation.objects.filter(author=profile_user).prefetch_related(
            'current_revision',
            'revisions',
            'image',
            'image__item',
            'image__item__collection'
        ).order_by("-created").all(), per_page)
        try:
            annotations_list = paginator.page(page)
        except PageNotAnInteger:
            annotations_list = paginator.page(1)
        except EmptyPage:
            annotations_list = paginator.page(paginator.num_pages)
        context['user_annotations'] = annotations_list
        context['profile_user'] = profile_user
        return render(request, 'iconolab/user_annotations.html', context)
    
class UserCommentedView(DetailView):
    model = User
    slug_field = 'id'
    
    def get_context_data(self, **kwargs):
        context = super(UserCommentedView, self).get_context_data(**kwargs)
        return context
    
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        profile_user = self.object
        context = self.get_context_data()
        page = request.GET.get('page', 1)
        per_page=request.GET.get('perpage', 10)
        paginator = Paginator(Annotation.objects.get_annotations_commented_for_user(profile_user), per_page)
        try:
            contributions_list = paginator.page(page)
        except PageNotAnInteger:
            contributions_list = paginator.page(1)
        except EmptyPage:
            contributions_list = paginator.page(paginator.num_pages)
        context['user_commented_annotations'] = contributions_list
        context['profile_user'] = profile_user
        return render(request, 'iconolab/user_commented.html', context)

class UserContributedView(DetailView):
    model = User
    slug_field = 'id'
    
    def get_context_data(self, **kwargs):
        context = super(UserContributedView, self).get_context_data(**kwargs)
        return context
    
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        profile_user = self.object
        context = self.get_context_data()
        page = request.GET.get('page', 1)
        per_page=request.GET.get('perpage', 10)
        paginator = Paginator(Annotation.objects.get_annotations_contributed_for_user(profile_user), per_page)
        try:
            commented_list = paginator.page(page)
        except PageNotAnInteger:
            commented_list = paginator.page(1)
        except EmptyPage:
            commented_list = paginator.page(paginator.num_pages)
        context['user_contributed_annotations'] = commented_list
        context['profile_user'] = profile_user
        return render(request, 'iconolab/user_contributed.html', context)

class UserCollectionAdminView(DetailView):
    model = User
    slug_field = 'id'
    
    def get_context_data(self, **kwargs):
        context = super(UserCollectionAdminView, self).get_context_data(**kwargs)
        return context
    
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        profile_user = self.object
        context = self.get_context_data()
        collection_name = kwargs.get("collection_name") 
        collection_qs = Collection.objects.filter(name=collection_name)
        if not request.user.is_staff and not request.user.is_authenticated or profile_user != request.user or not collection_qs.exists():
            return redirect(reverse_lazy('user_home', kwargs={'slug': profile_user.id}))
        collection = collection_qs.first()
        if collection not in profile_user.profile.managed_collections.all():
            return redirect(reverse_lazy('user_home', kwargs={'slug': profile_user.id}))
        
        annotation_queryset = Annotation.objects.distinct().filter(image__item__collection=collection).prefetch_related('current_revision', 'stats', 'image', 'image__item')
        
        # filtering
        comments_count_filter = request.GET.get("min_comments", "")
        if comments_count_filter and comments_count_filter.isdigit():
            comments_count_filter = int(comments_count_filter)
            context["qarg_min_comments"] = comments_count_filter
            annotation_queryset = annotation_queryset.filter(stats__comments_count__gte=comments_count_filter)
        revisions_count_filter = request.GET.get("min_revisions", "")
        if revisions_count_filter and revisions_count_filter.isdigit():
            revisions_count_filter = int(revisions_count_filter)
            context["qarg_min_revisions"] = revisions_count_filter
            annotation_queryset = annotation_queryset.filter(stats__submitted_revisions_count__gte=revisions_count_filter)
        relevancy_filter = request.GET.get("min_relevancy", "")
        if relevancy_filter and relevancy_filter.isdigit():
            min_relevancy = min(int(relevancy_filter), 5)
            context["qarg_min_relevancy"] = relevancy_filter
            annotation_queryset = annotation_queryset.filter(current_revision__tagginginfo__relevancy__gte=min_relevancy)
        accuracy_filter = request.GET.get("min_accuracy", "")
        if accuracy_filter and accuracy_filter.isdigit():
            min_accuracy = min(int(accuracy_filter), 5)
            context["qarg_min_accuracy"] = min_accuracy
            annotation_queryset = annotation_queryset.filter(current_revision__tagginginfo__accuracy__gte=min_accuracy)
        
        metacategories_filter = []
        mtcg_annotations_ids = {}
        filtering_on_metacategories = False
        context["qarg_metacategories_filters"] = {}
        for metacategory in collection.metacategories.all():
            # Default filter is 0
            mtcg_filter = request.GET.get("min_metacategory_"+str(metacategory.id), "0")
            # We ignore filters that aren't integers
            if mtcg_filter and mtcg_filter.isdigit(): 
                # For each metacategory we have a dict entry with key=id that will be a list of the annotation matching the filter
                mtcg_annotations_ids[str(metacategory.id)] = []
                # Queryarg for autocompleting the form on page load
                context["qarg_metacategories_filters"]["min_metacategory_"+str(metacategory.id)] = mtcg_filter
                # If we got this far we did a filter on metacategories
                filtering_on_metacategories = True
                for annotation in annotation_queryset.all():
                    if int(mtcg_filter) == 0 or MetaCategoriesCountInfo.objects.filter(metacategory=metacategory, annotation_stats_obj=annotation.stats, count__gte=int(mtcg_filter)).exists():
                         mtcg_annotations_ids[str(metacategory.id)].append(annotation.annotation_guid)
        if filtering_on_metacategories:
            # If we did a filter on metacategories we have several list of matching annotations. We only display the intersection of all these lists.
            annotation_queryset = annotation_queryset.filter(annotation_guid__in=
                list(
                     set.intersection(*[
                        set(value) for value in list(mtcg_annotations_ids.values())
                    ])
                )
            )
        
        # ordering
        ordering = []
        orderby_map = {
            "oldest": "created",
            "recent": "-created",
            "most_commented": "-stats__comments_count", 
            "most_tagged": "-stats__tag_count", 
            "most_revised": "-stats__submitted_revisions_count", 
            "most_viewed": "-stats__views_count"
        }
        for ordering_qarg in ["first", "second", "third", "fourth"]:
            if request.GET.get(ordering_qarg, "") in ["oldest", "recent", "most_commented", "most_tagged", "most_revised", "most_viewed"] and orderby_map.get(request.GET.get(ordering_qarg)) not in ordering:
                context["qarg_"+ordering_qarg] = request.GET.get(ordering_qarg)
                ordering.append(orderby_map.get(request.GET.get(ordering_qarg)))
        annotation_queryset = annotation_queryset.order_by(*ordering)
        context["collection_filtered_annotations"] = annotation_queryset
        context["collection"] = collection
        logger.debug(ordering)
        logger.debug(annotation_queryset)
        return render(request, 'iconolab/user_collection_admin.html', context)