from django.shortcuts import HttpResponse, get_object_or_404, render, redirect
from django.views.generic import View, DetailView
from django.urls 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, AnnotationRevision, IconolabComment, Image, MetaCategoriesCountInfo, Bookmark, BookmarkCategory
from iconolab.auth.forms import UserForm
from itertools import chain
from uuid import UUID
import logging

logger = logging.getLogger(__name__)

class UserHomeView(DetailView):
    """
        Homepage for user account, displays latest unread notifications, latest annotations created recap, latest contributions on annotations recap,
        latest annotations commented recap, also provides access to admin interface.
    """
    model = User
    slug_field = 'username'

    def get_context_data(self, **kwargs):
        context = super(UserHomeView, self).get_context_data(**kwargs)
        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']])

        user_created_annotations     = [ { 'action': 'create', 'annotation': a } for a in list(context['user_annotations']) ]
        user_contributed_annotations = [ { 'action': 'contribute', 'annotation': a['annotation_obj'] } for a in list(context['user_contributed_annotations']) ]
        user_commented_annotations   = [ { 'action': 'comment', 'annotation': a['annotation_obj'] } for a in list(context['user_commented_annotations']) ]

        annotations = list(chain(user_created_annotations, user_contributed_annotations, user_commented_annotations))

        context['user_activity'] = sorted(annotations, key=lambda a: a['annotation'].created, reverse=True)

        return context

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data()
        return render(request, 'iconolab/user_home.html', context)

class UserNotificationsView(View):
    """
        View that displays the notifications the user received
    """
    def get(self, request, *args, **kwargs):
        context = {}
        notifications = Notification.objects.filter(recipient=request.user)

        if request.user.is_authenticated and 'clear_notifications' in request.GET:
            Notification.objects.filter(recipient=request.user).mark_all_as_read()

        context['notifications_unread_ids'] = notifications.unread().values_list('id', flat=True)
        context['profile_user'] = request.user
        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):
    """
        View that displays the full paginated list of annotations created for the considered user
    """
    model = User
    slug_field = 'username'

    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 UserBookmarksView(DetailView):

    model = User
    slug_field = 'username'

    def get_context_data(self, **kwargs):
        context = super(UserBookmarksView, 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()

        bookmark_categories = BookmarkCategory.objects.filter(user=profile_user).all()

        context['bookmark_categories'] = bookmark_categories
        context['profile_user'] = profile_user

        bookmarks_by_category = []
        for bookmark_category in bookmark_categories:
            bookmarks = Bookmark.objects.filter(category__user=profile_user, category=bookmark_category).all()
            if bookmarks.count() > 0:
                bookmarks_by_category.append({
                    'category': bookmark_category,
                    'bookmarks': bookmarks
                })

        context['bookmarks_by_category'] = bookmarks_by_category

        return render(request, 'iconolab/user_bookmarks.html', context)

class BookmarkDeleteView(View):

    def post(self, request, *args, **kwargs):

        if request.user.is_authenticated:
            bookmark_id = kwargs.get('bookmark')
            bookmark = Bookmark.objects.get(id=bookmark_id)
            if bookmark.category.user == request.user:
                bookmark.delete()
            else:
                return redirect(reverse('home'))
        else:
            return redirect(reverse('home'))

        return redirect(reverse('user_bookmarks', kwargs={'slug': request.user.username}))

class BookmarkEditView(View):

    def post(self, request, *args, **kwargs):

        if request.user.is_authenticated:
            bookmark_id = kwargs.get('bookmark')
            bookmark = Bookmark.objects.get(id=bookmark_id)
            if bookmark.category.user == request.user:
                bookmark.category = BookmarkCategory.objects.get(id=request.POST.get('category'))
                bookmark.save()
            else:
                return redirect(reverse('home'))
        else:
            return redirect(reverse('home'))

        return redirect(reverse('user_bookmarks', kwargs={'slug': request.user.username}))

class UserCommentedView(DetailView):
    """
        View that displays the full paginated list of annotations on which the considered user has commented
    """
    model = User
    slug_field = 'username'

    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):
    """
        View that displays the full paginated list of annotations on which the considered user has submitted at least one revision
    """
    model = User
    slug_field = 'username'

    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(View):
    """
        View that displays the admin panel, allowing collection admin to filter and order annotations on several criterias
    """
    def get(self, request, *args, **kwargs):

        profile_user = request.user
        context = {}
        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.username}))
        collection = collection_qs.first()
        if collection not in profile_user.profile.managed_collections.all():
            return redirect(reverse_lazy('user_home', kwargs={'slug': profile_user.username}))

        context['profile_user'] = profile_user
        context['collection'] = collection

        context['awaiting_revisions'] = AnnotationRevision.objects.filter(
            state=AnnotationRevision.AWAITING,
            annotation__image__item__collection=collection
        ).order_by('-created')

        return render(request, 'iconolab/user_collection_admin.html', context)

class UserSettingsView(View):

    def get(self, request, *args, **kwargs):
        context = {}
        context['profile_user'] = request.user
        context['user_form'] = UserForm(instance=request.user)

        return render(request, 'iconolab/user_settings.html', context)

    def post(self, request, *args, **kwargs):
        context = {}
        context['profile_user'] = request.user

        user_form = UserForm(data=request.POST, instance=request.user)
        if user_form.is_valid():
            user = user_form.save(commit=False)
            user.save()
            return redirect(reverse('user_settings', kwargs={'slug': user.username}))

        context['user_form'] = user_form

        return render(request, 'iconolab/user_settings.html', context)

class UserCollectionsView(View):

    def get(self, request, *args, **kwargs):
        context = {}
        context['profile_user'] = request.user

        return render(request, 'iconolab/user_collections.html', context)
