import json

from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.mail import send_mail
from django.db.models import Q
from django.http import Http404, HttpResponse
from django.urls import reverse
from django.views import View
from django.views.generic import DetailView
from django.views.generic.base import TemplateView
from django.views.generic.edit import CreateView

from dal import autocomplete

from apps.files.models import File

from .models import CaseStudy, CaseStudyDraft, SpatialRefSys
from .forms import ShortCaseStudyForm, LongCaseStudyForm


NOTIFY_MESSAGE = """
Hello,

Someone has submitted a new case study to the Ojuso website.  Please
follow the below link to look over and approve it:

%s%s

– Case Study Robot

"""

class Map(TemplateView):
    template_name = "map/index.html"


class Create(LoginRequiredMixin, TemplateView):
    template_name = "map/how_much_time.html"


class BaseForm(LoginRequiredMixin, CreateView):
    """View for base case study form."""
    template_name = 'map/form.html'
    success_url = '/case-study/create/success/'
    model = CaseStudy

    def send_email(self):
        """Sends email to moderator to approve case study."""

        send_mail(
            'New case study submitted',
            NOTIFY_MESSAGE % (
                settings.SITE_URL,
                reverse('admin:map_casestudy_change', args=[self.object.id])
            ),
            'noreply@ojuso.org',
            [settings.DATABASE_EMAIL],
            fail_silently=False,
        )

    def form_valid(self, form):
        form.cleaned_data.pop('official_project_documents', None)
        form.cleaned_data.pop('other_documents', None)
        form.cleaned_data.pop('shapefiles', None)
        form.cleaned_data.pop('images', None)

        self.object = form.save()

        self.object.official_project_documents = form.cleaned_data.get(
            'official_project_document_files', []
        )
        self.object.other_documents = form.cleaned_data.get(
            'other_documents_files', []
        )
        self.object.shapefiles = form.cleaned_data.get(
            'shapefiles_files', []
        )

        self.object.author = self.request.user
        self.object.save()

        self.send_email()

        # Delete the corresponding draft
        try:
            draft = CaseStudyDraft.objects.get(author=self.request.user)
            draft.delete()
        except CaseStudyDraft.DoesNotExist:
            pass

        return super().form_valid(form)


class ShortForm(BaseForm):
    """View for short version of case study form."""
    form_class = ShortCaseStudyForm


class LongForm(BaseForm):
    """View for long version of case study form."""
    form_class = LongCaseStudyForm


class FormSuccess(TemplateView):
    template_name = 'map/form-success.html'


class CaseStudyDetail(DetailView):
    template_name = "map/detail.html"
    model = CaseStudy
    context_object_name = "case_study"


class SpatialRefSysAutocomplete(autocomplete.Select2QuerySetView):
    def get_queryset(self):
        qs = SpatialRefSys.objects.all()

        if self.q:
            qs = qs.filter(
                Q(auth_name__icontains=self.q)
                | Q(auth_srid__icontains=self.q)
            )

        return qs


class Drafts(LoginRequiredMixin, View):
    """Retrieve or save a draft."""

    def get_object(self, request):
        try:
            return CaseStudyDraft.objects.get(author=request.user)
        except:
            return None

    def get(self, request):
        draft = self.get_object(request)
        if draft == None:
            return HttpResponse(status=404) # Not Found
        else:
            return HttpResponse(draft.data, content_type="application/json")

    def put(self, request):
        # Find an existing object is there is one
        draft = self.get_object(request)
        if draft == None:
            # If there isn't, create a new draft...
            draft = CaseStudyDraft(author=request.user, data=request.body)
            draft.save()
            return HttpResponse(status=201) # Created
        else:
            draft.data = request.body
            draft.save()
            return HttpResponse(status=200) # OK

    def delete(self, request):
        draft = self.get_object(request)

        if draft != None:
            data = json.loads(draft.data)

            for k in ['official_project_documents', 'other_documents',
                      'shapefiles']:

                try:
                    items = list(filter(
                        lambda x: (
                            x['name'] == '{0}_files'.format(k)
                            and x['value'] != ''
                        ), data['data']['form']
                    ))
                except KeyError:
                    continue
                    
                try:
                    items = items[0]['value'].split(',')
                except IndexError:
                    continue

                for item in items:
                    try:
                        f = File.objects.get(id=item)
                        if f.user != self.request.user:
                            continue
                        f.delete()
                    except File.DoesNotExist:
                        continue

            draft.delete()

        return HttpResponse(status=204)