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

''' Django views. '''
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic import ListView
from django.views import View
from django.http import Http404
from django.contrib import messages
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin

from django.contrib.messages.views import SuccessMessageMixin

from .forms import (
    ExplorerCreationForm, 
    PlaceForm, 
    PlaceImageCreateForm
)
from .models import Place, PlaceImage, Voucher

# Create your views here.

# BaseView that checks if user is logged in.
class IsAuthenticated(LoginRequiredMixin, View):
    redirect_field_name = 'redirect_to'

# BaseView that checks if logged in user is submitter of place.
class IsSubmitter(UserPassesTestMixin, View):
    def test_func(self):
        """ Check if user is eligible to modify place. """
        if self.request.user.is_superuser:
            return True
        
        # Check if currently logged in user was the submitter
        place_obj = self.get_object()

        if self.request.user == place_obj.submitted_by:
            return True

        messages.error(
            self.request, 'You do not have permission to do this.')
        return False

class SignUpView(SuccessMessageMixin, CreateView):
    form_class = ExplorerCreationForm
    success_url = reverse_lazy('login')
    template_name = 'signup.html'
    success_message = 'User created.'

class PlaceListView(IsAuthenticated, ListView):
    paginate_by = 5
    model = Place
    template_name = 'place/place_list.html'
    ordering = ['name']

class PlaceDetailView(IsAuthenticated, View):
    def get(self, request, pk):
        context = {
            'place': Place.objects.get(pk=pk)
        }
        return render(request, 'place/place_detail.html', context)

class HomeView(View):
    def get(self, request, *args, **kwargs):
        place_list = Place.objects.all().order_by('-submitted_when')[:10]
        place_map_center = Place.average_latlon(place_list)
        context = {
            'place_list': place_list,
            'place_map_center': place_map_center
        }
        return render(request, 'home.html', context)

class PlaceUpdateView(IsAuthenticated, IsSubmitter, SuccessMessageMixin, UpdateView):
    template_name = 'place/place_update.html'
    model = Place
    form_class = PlaceForm
    success_message = 'Successfully updated place.'

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

class PlaceCreateView(IsAuthenticated, View):

    def get(self, request, *args, **kwargs):
        place_image_form = PlaceImageCreateForm()
        place_form = PlaceForm()

        context = {
            'place_form': place_form,
            'place_image_form': place_image_form
        }
        return render(request, 'place/place_create.html', context)

    def post(self, request, *args, **kwargs):
        place_form = PlaceForm(request.POST)

        if place_form.is_valid():
            submitter = request.user
            place = place_form.save(commit=False)
            # Save logged in user as "submitted_by"
            place.submitted_by = submitter
            place.save()

            if request.FILES:
                self._apply_multipart_image_upload(
                    files=request.FILES.getlist('filename'),
                    place=place, 
                    submitter=submitter
                )
            
            kwargs_to_pass = {
                'pk': place.pk
            }

            messages.success(
                self.request, 'Successfully created place.')
            return redirect(reverse_lazy('place_detail', kwargs=kwargs_to_pass))
        
        else:
            context = {
                'form': form_place
            }

            # Usually the browser should have checked the form before sending.
            messages.error(
                self.request, 'Please fill in all required fields.')
            return render(request, 'place/place_create.html', context)

    def _apply_multipart_image_upload(self, files, place, submitter):
        for image in files:
            place_image = PlaceImage.objects.create(
                filename=image,
                place=place,
                submitted_by=submitter
            )
            place_image.save()

class PlaceDeleteView(IsAuthenticated, IsSubmitter, DeleteView):
    template_name = 'place/place_delete.html'
    model = Place
    success_message = 'Successfully deleted place.'
    success_url = reverse_lazy('place_list')
    success_message = 'Place deleted'

    def delete(self, request, *args, **kwargs):
        messages.success(self.request, self.success_message)
        return super().delete(request, *args, **kwargs)
