"""
Soubor sloužící k deklaraci jednotlivých „views“ (nejčastěji funkce beroucí request
a vracející :func:`django.shortcuts.render` respektive nějakou response, nebo
třídy většinou rozšiřující nějakou třídu z :mod:`django.views.generic`)
"""
from django.shortcuts import get_object_or_404, render
from django.views import generic
from django.utils.translation import ugettext as _
from django.conf import settings
from django.http import HttpResponseForbidden
from django.core.mail import send_mail
from django.db.models import Count,Q

from .models import Oprava,Komentar,KorekturovanePDF, Organizator
from .forms import OpravaForm

import subprocess
import shutil
import os

class KorekturyListView(generic.ListView):
	model = KorekturovanePDF
	# Nefunguje, filtry se vubec nepouziji
	queryset = KorekturovanePDF.objects.annotate(
		k_oprave_cnt=Count('oprava',distinct=True,filter=Q(oprava__status='k_oprave')),
		opraveno_cnt=Count('oprava',distinct=True,filter=Q(oprava__status='opraveno')),
		neni_chyba_cnt=Count('oprava',distinct=True,filter=Q(oprava__status='neni_chyba')),
		k_zaneseni_cnt=Count('oprava',distinct=True,filter=Q(oprava__status='k_zaneseni')),
		)
	template_name = 'korektury/seznam.html'

class KorekturyAktualniListView(KorekturyListView):
	def get_queryset(self, *args, **kwargs):
		queryset=super().get_queryset()
		queryset=queryset.exclude(status="zastarale")
		return queryset

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



class KorekturyZastaraleListView(KorekturyListView):
	def get_queryset(self, *args, **kwargs):
		queryset=super().get_queryset()
		queryset=queryset.filter(status="zastarale").order_by("-cas")
		return queryset

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

class KorekturySeskupeneListView(KorekturyAktualniListView):
	template_name = 'korektury/seskupeny_seznam.html'

	# {% regroup %} potřebuje dostat správně setříděné názvy, aby nedělal duplikáty
	def get_queryset(self, *args, **kwargs):
		qs = super().get_queryset(**kwargs)
		return reversed(sorted(qs, key=lambda it: it.cislo_a_tema))

### Korektury
class KorekturyView(generic.TemplateView):
	model = Oprava
	template_name = 'korektury/opraf.html'
	form_class = OpravaForm

	def post(self, request, *args, **kwargs):
		form = self.form_class(request.POST)
		q = request.POST
		scroll = q.get('scroll')

		# prirazeni autora podle prihlaseni
		autor_user = request.user
		# pokud existuje ucet (user), ale neni to organizator = 403
		autor = Organizator.objects.filter(osoba__user=autor_user).first()
		if not autor:
			return HttpResponseForbidden()

		if not scroll:
			scroll = 0

		action = q.get('action')
		if (action == ''):  # Přidej
			x = int(q.get('x'))
			y = int(q.get('y'))
			text = q.get('txt')
			strana = int(q.get('img-id')[4:])
			pdf = KorekturovanePDF.objects.get(id=q.get('pdf'))

			op = Oprava(x=x,y=y, autor=autor, text=text, strana=strana,pdf = pdf)
			op.save()
			self.send_email_notification_komentar(op,autor)
		elif (action == 'del'):
			id = int(q.get('id'))
			op = Oprava.objects.get(id=id)
			op.delete()
		elif (action == 'update'):
			id = int(q.get('id'))
			op = Oprava.objects.get(id=id)
			text = q.get('txt')
			op.autor = autor
			op.text = text
			op.save()
		elif (action == 'undone'):
			id = int(q.get('id'))
			op = Oprava.objects.get(id=id)
			op.status = op.STATUS_K_OPRAVE
			op.save()
		elif (action == 'done'):
			id = int(q.get('id'))
			op = Oprava.objects.get(id=id)
			op.status = op.STATUS_OPRAVENO
			op.save()
		elif (action == 'ready'):
			id = int(q.get('id'))
			op = Oprava.objects.get(id=id)
			op.status = op.STATUS_K_ZANESENI
			op.save()
		elif (action == 'wontfix'):
			id = int(q.get('id'))
			op = Oprava.objects.get(id=id)
			op.status = op.STATUS_NENI_CHYBA
			op.save()
		elif (action == 'comment'):
			id = int(q.get('id'))
			op = Oprava.objects.get(id=id)
			text = q.get('txt')
			kom = Komentar(oprava=op,autor=autor,text=text)
			kom.save()
			self.send_email_notification_komentar(op,autor)
		elif (action == 'update-comment'):
			id = int(q.get('id'))
			kom = Komentar.objects.get(id=id)
			text = q.get('txt')
			kom.text = text
			kom.autor = autor
			kom.save()
		elif (action == 'del-comment'):
			id = int(q.get('id'))
			kom = Komentar.objects.get(id=id)
			kom.delete()
		elif (action == 'set-state'):
			pdf = KorekturovanePDF.objects.get(id=q.get('pdf'))
			if (q.get('state') == 'adding'):
				pdf.status = pdf.STATUS_PRIDAVANI
			elif (q.get('state') == 'comitting'):
				pdf.status = pdf.STATUS_ZANASENI
			elif (q.get('state') == 'deprecated'):
				pdf.status = pdf.STATUS_ZASTARALE
			pdf.save()
		context = self.get_context_data()
		context['scroll'] = scroll
		context['autor'] = autor
		return render(request, 'korektury/opraf.html',context)

	def send_email_notification_komentar(self, oprava, autor):
		''' Rozesle e-mail pri pridani komentare / opravy,
			ktery obsahuje text vlakna opravy.
		'''

		# parametry e-mailu
		#odkaz = "https://mam.mff.cuni.cz/korektury/{}/".format(oprava.pdf.pk)
		from django.urls import reverse
		odkaz = self.request.build_absolute_uri(reverse('korektury', kwargs={'pdf': oprava.pdf.pk}))
		odkaz = f"{odkaz}#op{oprava.id}-pointer"
		from_email = 'korekturovatko@mam.mff.cuni.cz'
		subject = 'Nová korektura od {} v {}'.format(autor, oprava.pdf.nazev)
		texty = [(oprava.autor.osoba.plne_jmeno(),oprava.text)]
		for kom in Komentar.objects.filter(oprava=oprava):
			texty.append((kom.autor.osoba.plne_jmeno(),kom.text))
		optext = "\n\n\n".join([": ".join(t) for t in texty])
		text = u"Text komentáře:\n\n{}\n\n=== Konec textu komentáře ===\n\
				\nodkaz do korekturovátka: {}\n\
				\nVaše korekturovátko\n".format(optext, odkaz)

		# Prijemci e-mailu
		emails = set()
		# e-mail autora korektury
		email = oprava.autor.osoba.email
		if email:
			emails.add(email)

		# nalezeni e-mailu na autory komentaru
		for komentar in oprava.komentar_set.all():
			email_komentujiciho = komentar.autor.osoba.email
			if email_komentujiciho:
				emails.add(email_komentujiciho)

		# zodpovedny org
		if oprava.pdf.org:
			email_zobpovedny = oprava.pdf.org.osoba.email
			if email_zobpovedny:
				emails.add(email_zobpovedny)

		# odstran e-mail autora opravy
		email = autor.osoba.email
		if email:
			emails.discard(email)

		if not settings.POSLI_MAILOVOU_NOTIFIKACI:
			print("Poslal bych upozornění na tyto adresy: ", " ".join(emails))
			print("---- Upozornění:")
			print(text)
			print("---- Konec upozornění")
			return

		send_mail(subject, text, from_email, list(emails))

	def get_context_data(self, **kwargs):
		context = super().get_context_data(**kwargs)
		pdf = get_object_or_404(KorekturovanePDF, id=self.kwargs['pdf'])
		context['pdf'] = pdf
		context['img_prefix'] = pdf.get_prefix()
		context['img_path'] = settings.KOREKTURY_IMG_DIR
		context['img_indexes'] = range(pdf.stran) 
		context['form_oprava'] = OpravaForm()
		opravy = Oprava.objects.filter(pdf=self.kwargs['pdf'])
		zasluhy = {}
		for o in opravy:
			if o.autor in zasluhy:
				zasluhy[o.autor]+=1
			else:
				zasluhy[o.autor]=1
			o.komentare = o.komentar_set.all()
			for k in o.komentare:
				if k.autor in zasluhy:
					zasluhy[k.autor] += 1
				else:
					zasluhy[k.autor] = 1
		zasluhy = [
			{'autor': jmeno, 'pocet': pocet}
			for (jmeno, pocet) in zasluhy.items()
		]
		zasluhy.sort(key=lambda z: z['pocet'], reverse=True)

		strany = set(o.strana for o in opravy)
		opravy_na_stranu = [{'strana': s, 'op_id': opravy.filter(strana=s)} for s in strany]
		context['opravy_strany'] = opravy_na_stranu

		context['k_oprave_cnt'] = opravy.filter(status='k_oprave').count() 
		context['opraveno_cnt'] = opravy.filter(status='opraveno').count() 
		context['neni_chyba_cnt'] = opravy.filter(status='neni_chyba').count() 
		context['k_zaneseni_cnt'] = opravy.filter(status='k_zaneseni').count() 
		
		context['opravy'] = opravy
		context['zasluhy'] = zasluhy
		return context

	def form_valid(self,form):
		return super().form_valid(form)