#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django.views import View
from django.views.generic.edit import CreateView
from django.views.generic.detail import SingleObjectMixin
from django.views.generic import ListView

from django.contrib import messages
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin

from django.shortcuts import redirect, get_object_or_404
from django.urls import reverse_lazy, reverse
from django.utils.translation import ugettext_lazy as _

from lostplaces.models import Place
from lostplaces.common import redirect_referer_or

class IsAuthenticatedMixin(LoginRequiredMixin, View):
    '''
    A view mixin that checks wether a user is logged in or not.
    If the user is not logged in, he gets redirected to 
    the login page.
    '''
    login_url = reverse_lazy('login')
    permission_denied_message = _('Please login to proceed')

    def handle_no_permission(self):
        if not self.request.user.is_authenticated:
            messages.error(self.request, self.permission_denied_message)
        return super().handle_no_permission()

class IsPlaceSubmitterMixin(UserPassesTestMixin, View):
    '''
    A view mixin that checks wether a user is the submitter
    of a place, throws 403 if the user is not. The subclass 
    has to provide a get_place method, which returns the
    place to check.
    '''
    place_submitter_error_message = None

    def get_place(self):
        pass

    def test_func(self):
        """ Check if user is eligible to modify place. """

        if not hasattr(self.request, 'user'):
            return False

        if self.request.user.is_superuser:
            return True
        
        # Check if currently logged in user was the submitter
        place_obj = self.get_place()

        if place_obj and hasattr(place_obj, 'submitted_by') and self.request.user.explorer == place_obj.submitted_by:
            return True

        if self.place_submitter_error_message:
            messages.error(self.request, self.place_submitter_error_message)
        return False

class IsEligibleToSeePlaceMixin(UserPassesTestMixin):
    not_eligible_to_see_message = None

    def get_place(self):
        pass

    def test_func(self):
        if not hasattr(self.request, 'user'):
            return False

        if self.request.user.explorer.is_eligible_to_see(self.get_place()):
            return True

        if self.not_eligible_to_see_message:
            messages.error(self.request, self.not_eligible_to_see_message)
        return False

class PlaceAssetCreateView(IsAuthenticatedMixin, SuccessMessageMixin, CreateView):
    """
    Abstract View for creating a place asset (i.e. PlaceImage) 
    """
    model = None
    template_name = ''
    success_message = ''

    def get(self, request, place_id, *args, **kwargs):
        self.place = get_object_or_404(Place, pk=place_id)
        return super().get(request, *args, **kwargs)

    def post(self, request, place_id, *args, **kwargs):
        self.place = get_object_or_404(Place, pk=place_id)
        response = super().post(request, *args, **kwargs)
        self.object.place = self.place
        self.object.submitted_by = request.user.explorer
        self.object.save()
        return response

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['place'] = self.place
        return context

    def get_success_url(self):
        return reverse_lazy('place_detail', kwargs={'pk': self.place.id})

class PlaceAssetDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, SingleObjectMixin, View):
    model = None
    success_message = ''
    permission_denied_message = ''

    def get_place(self):
        place_id = self.get_object().place.id
        return Place.objects.get(pk=place_id)

    def test_func(self):
        can_edit_place = super().test_func()
        if can_edit_place:
            return True
        
        if self.get_object().submitted_by == self.request.user.explorer:
            return True
        
        messages.error(self.request, self.permission_denied_message)
        return False

    def get(self, request, *args, **kwargs):
        place_id = self.get_object().place.id
        self.get_object().delete()
        messages.success(self.request, self.success_message)
        return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place_id}))


class LevelCapPlaceListView(ListView):
    model = Place
    
    def get_queryset(self):
        return self.request.user.explorer.get_places_eligible_to_see()