# coding:utf-8

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse
from django.urls import reverse
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
from django.views import generic
from django.utils.translation import ugettext as _
from django.http import Http404,HttpResponseBadRequest,HttpResponseRedirect
from django.db.models import Q
from django.views.decorators.csrf import ensure_csrf_cookie
from django.contrib.auth import authenticate, login

from .models import Problem, Cislo, Reseni, Nastaveni, Rocnik, Soustredeni, Organizator, Resitel, Novinky, Soustredeni_Ucastnici, Pohadka, Tema, Clanek
#from .models import VysledkyZaCislo, VysledkyKCisluZaRocnik, VysledkyKCisluOdjakziva
from . import utils
from .unicodecsv import UnicodeWriter
from .forms import NameForm

from datetime import timedelta, date, datetime
from itertools import groupby
import tempfile
import subprocess
import shutil
import os
import os.path as op
from django.conf import settings
import unicodedata
import json
import traceback
import sys
import csv


def verejna_temata(rocnik):
	"""Vrací queryset zveřejněných témat v daném ročníku.
	"""
	return Problem.objects.filter(typ=Problem.TYP_TEMA, cislo_zadani__rocnik=rocnik, cislo_zadani__verejne_db=True).order_by('kod')


def AktualniZadaniView(request):
	nastaveni = get_object_or_404(Nastaveni)
	verejne = nastaveni.aktualni_cislo.verejne()
	problemy = Problem.objects.filter(cislo_zadani=nastaveni.aktualni_cislo).filter(stav = 'zadany')
	ulohy = problemy.filter(typ = 'uloha').order_by('kod')
	serialy = problemy.filter(typ = 'serial').order_by('kod')
	jednorazove_problemy = [ulohy, serialy]
	return render(request, 'seminar/zadani/AktualniZadani.html',
			{'nastaveni': nastaveni,
			 'jednorazove_problemy': jednorazove_problemy,
			 'temata': verejna_temata(nastaveni.aktualni_rocnik),
			 'verejne': verejne,
				},
			)

def ZadaniTemataView(request):
	nastaveni = get_object_or_404(Nastaveni)
	temata = verejna_temata(nastaveni.aktualni_rocnik)
	for t in temata:
		if request.user.is_staff:
			t.prispevky = t.prispevek_set.filter(problem=t)
		else:
			t.prispevky = t.prispevek_set.filter(problem=t, zverejnit=True)
	return render(request, 'seminar/zadani/Temata.html',
		{
			'temata': temata,
		}
	)


#def ZadaniAktualniVysledkovkaView(request):
#	nastaveni = get_object_or_404(Nastaveni)
#	# Aktualni verejna vysledkovka
#	vysledkovka = vysledkovka_rocniku(nastaveni.aktualni_rocnik)
#	# kdyz neni verejna vysledkovka, tak zobraz starou
#	if not vysledkovka:
#		try:
#			minuly_rocnik = Rocnik.objects.get(
#				prvni_rok=(nastaveni.aktualni_rocnik.prvni_rok-1))
#			vysledkovka = vysledkovka_rocniku(minuly_rocnik)
#		except ObjectDoesNotExist:
#			pass
#	# vysledkovka s neverejnyma vysledkama
#	vysledkovka_s_neverejnymi = vysledkovka_rocniku(nastaveni.aktualni_rocnik, jen_verejne=False)
#	return render(
#		request,
#		'seminar/zadani/AktualniVysledkovka.html',
#		{
#			'nastaveni': nastaveni,
#			'vysledkovka': vysledkovka,
#			'vysledkovka_s_neverejnymi': vysledkovka_s_neverejnymi,
#		}
#	)


### Titulni strana

class TitulniStranaView(generic.ListView):
	model = Novinky
	template_name='seminar/titulnistrana.html'
	queryset = Novinky.objects.order_by('-datum')[:5]

	def get_context_data(self, **kwargs):
		context = super(TitulniStranaView, self).get_context_data(**kwargs)
		nastaveni = get_object_or_404(Nastaveni)

		# zjisteni spravneho terminu
		if nastaveni.aktualni_cislo.datum_deadline_soustredeni:
			cas_deadline_soustredeni = nastaveni.aktualni_cislo.\
				datum_deadline_soustredeni
			if (datetime.now().date() <= cas_deadline_soustredeni):
				cas_deadline = cas_deadline_soustredeni
				deadline_soustredeni = True
			else:
				cas_deadline = nastaveni.aktualni_cislo.datum_deadline
				deadline_soustredeni = False
		else:
			cas_deadline = nastaveni.aktualni_cislo.datum_deadline
			deadline_soustredeni = False

		# Pokud neni zverejnene cislo nezverejnuj odpocet
		if nastaveni.aktualni_cislo.verejne():
			# pokus se zjistit termin odeslani a pokud neni zadany,
			# nezverejnuj odpocet
			context['deadline_soustredeni'] = deadline_soustredeni
			try:
				context['dead'] = datetime.combine(cas_deadline,
												 datetime.max.time())
				context['ted'] = datetime.now()
			except:
				context['dead'] = None
		else:
			context['dead'] = None
			context['deadline_soustredeni'] = deadline_soustredeni
		return context

class StareNovinkyView(generic.ListView):
	model = Novinky
	template_name = 'seminar/stare_novinky.html'
	queryset = Novinky.objects.filter(zverejneno=True).order_by('-datum')

### Co je M&M


# Organizatori
def aktivniOrganizatori(datum=date.today()):
	return Organizator.objects.exclude(
		organizuje_do__isnull=False,
		organizuje_do__lt=datum
	).order_by('osoba__jmeno')


class CojemamOrganizatoriView(generic.ListView):
	model = Organizator
	template_name = 'seminar/cojemam/organizatori.html'
	queryset = aktivniOrganizatori()

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


class CojemamOrganizatoriStariView(generic.ListView):
	model = Organizator
	template_name = 'seminar/cojemam/organizatori.html'
	queryset = Organizator.objects.exclude(
		id__in=aktivniOrganizatori()).order_by('-organizuje_do')

### Archiv


class ArchivView(generic.ListView):
	model = Rocnik
	template_name='seminar/archiv/cisla.html'

	def get_context_data(self, **kwargs):
		context = super(ArchivView, self).get_context_data(**kwargs)

		vyska = 297  # px
		sirka = 210  # px

		cisla = Cislo.objects.filter(verejne_db=True)[:10]

		png_dir = op.join(settings.MEDIA_ROOT, "cislo", "png")

		# seznam [(url obrázku, číslo)]
		urls = []

		for i, c in enumerate(cisla):
			if not c.pdf:
				continue
			filename = os.path.split(c.pdf.file.name)[1].split(".")[0]
			png_filename = "{}-{}px.png".format(filename, vyska)

			# Pokud obrázek neexistuje nebo není aktuální, vytvoř jej
			png_path = op.join(png_dir, png_filename)
			if not op.exists(png_path) or \
					op.getmtime(png_path) < op.getmtime(c.pdf.path):

				subprocess.call([
					"convert",
					"-density", "180x180",
					"-geometry", "{}x{}".format(vyska, vyska),
					"-background", "white",
					"-flatten",
					"-rotate", str(90 * i),
					"{}[0]".format(c.pdf.path),  # titulní strana
					png_path
				])

			urls.append(
				(op.join(settings.MEDIA_URL, "cislo", "png", png_filename), c)
			)
			vyska, sirka = sirka, vyska / 2

		tags = []

		def spirala(urls, tags, idx):
			"""Rekurzivně prochází urls a generuje strom elementů do tags"""
			if idx >= len(urls):
				return

			img_url, cislo = urls[idx]
			tags.append(
				"<div style='top:{}%;left:{}%;width:{}%;height:{}%;'>"
				.format(
					50 if idx % 4 == 2 else 0,
					50 if idx % 4 == 1 else 0,
					50 if idx % 2 == 1 else 100,
					50 if idx > 0 and idx % 2 == 0 else 100
				)
			)
			tags.append("<a href='{}' title='{}'>".format(
				cislo.verejne_url(), cislo.kod()
			))
			tags.append(
				"<img src='{}' style='top:{}%;left:{}%;width:{}%;height:{}%;'>"
				.format(
					img_url,
					50 if idx % 4 == 3 else 0,
					50 if idx % 4 == 2 else 0,
					50 if idx % 2 == 0 else 100,
					50 if idx % 2 == 1 else 100
				)
			)
			tags.append("</a>")
			spirala(urls, tags, idx + 1)
			tags.append("</div>")
		spirala(urls, tags, 0)

		context["nahledy"] = "\n".join(tags)
		return context


def sloupec_s_poradim(vysledky):
	# počet řešitelů ve výsledkovce nad aktuálním
	lepsich_resitelu = 0

	poradi_l = []
	# projdeme skupiny řešitelů se stejným počtem bodů
	for skupina in (list(x) for _, x in groupby(vysledky, lambda x: x.body)):

		# připravíme si obsahy buněk ve sloupci pořadí pro skupinu
		if len(skupina) == 1:
			poradi_l += ["{}.".format(lepsich_resitelu + 1)]
		# je-li účastníků se stejným počtem bodů víc, pořadí (rozsah X.-Y.) je jen u prvního
		else:
			poradi_l += [u"{}.–{}.".format(lepsich_resitelu + 1, lepsich_resitelu + len(skupina))] + [""] * (len(skupina)-1)
		lepsich_resitelu += len(skupina)
	#pomlcka je opravdu pomlcka v unicode!!dulezite pro vysledkovku v TeXu

	return poradi_l


#def vysledkovka_rocniku(rocnik, jen_verejne=True):
#	"""Přebírá ročník (např. context["rocnik"]) a vrací výsledkovou listinu ve
#	formě vhodné pro šablonu "seminar/vysledkovka_rocniku.html"
#	"""
#
#	#vyberu vsechny vysledky z rocniku
#	cisla_v_rocniku = VysledkyKCisluZaRocnik.objects.filter(cislo__rocnik=rocnik).order_by('cislo')
#	if jen_verejne:
#		cisla_v_rocniku = cisla_v_rocniku.filter(cislo__verejna_vysledkovka=True)
#
#	#pokud žádné nejsou, výsledkovka se nezobrazí
#	if not cisla_v_rocniku:
#		return None
#
#	#vybere vsechny vysledky z posledniho (verejneho) cisla a setridi sestupne dle bodu
#	vysledky = list(cisla_v_rocniku.filter(cislo = cisla_v_rocniku[0].cislo).order_by('-body', 'resitel__prijmeni', 'resitel__jmeno').select_related('resitel'))
#
#	class Vysledkovka:
#		def __init__(self):
#			self.rocnik = rocnik.rocnik
#			self.radky = []
#			self.cisla = []
#
#	vysledkovka = Vysledkovka()
#	vysledkovka.cisla = (rocnik.verejne_vysledkovky_cisla() if jen_verejne else rocnik.cisla.all().order_by('cislo'))
#
#	# doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině
#	for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky):
#		v.poradi = poradi
#		v.resitel.rocnik = v.resitel.rocnik(rocnik)
#
#		verejne_vysl_odjakziva = VysledkyKCisluOdjakziva.objects.filter(cislo__rocnik=rocnik, cislo=cisla_v_rocniku[0].cislo)
#		if jen_verejne:
#			verejne_vysl_odjakziva = verejne_vysl_odjakziva.filter(cislo__verejna_vysledkovka=True)
#
#		v.body_odjakziva = verejne_vysl_odjakziva.filter(resitel = v.resitel)[0].body
#		v.titul = v.resitel.get_titul(v.body_odjakziva)
#		v.body_rocnik = v.body
#		v.body_cisla = []
#
#		#pokud pro dany rok a cislo nema resitel vysledky, ma defaultne 0
#		for cis in vysledkovka.cisla:
#			if not jen_verejne or cis.verejna_vysledkovka:
#				#seznam vysledku se spravnym rocnikem a cislem pro resitele
#				#zobrazim jen je-li vysledkovka verejna
#				body_za_cislo = VysledkyZaCislo.objects.filter(cislo__rocnik=rocnik).filter(cislo = cis).filter(resitel = v.resitel)
#				if body_za_cislo:
#					#neprazdne vysledky by mely obsahovat prave jeden vysledek
#					v.body_cisla.append(body_za_cislo[0].body)
#				else:
#					#resitel nema za cislo body
#					v.body_cisla.append(0)
#
#		vysledkovka.radky.append(v)
#
#	return vysledkovka


class RocnikView(generic.DetailView):
	model = Rocnik
	template_name = 'seminar/archiv/rocnik.html'

	# Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
	def get_object(self, queryset=None):
		if queryset is None:
			queryset = self.get_queryset()
		rocnik_arg = self.kwargs.get('rocnik')
		queryset = queryset.filter(rocnik=rocnik_arg)

		try:
			obj = queryset.get()
		except queryset.model.DoesNotExist:
			raise Http404(_("No %(verbose_name)s found matching the query") %
						{'verbose_name': queryset.model._meta.verbose_name})
		return obj

	def get_context_data(self, **kwargs):
		context = super(RocnikView, self).get_context_data(**kwargs)

		#context['vysledkovka'] = vysledkovka_rocniku(context["rocnik"])
		#context['vysledkovka_s_neverejnymi'] = vysledkovka_rocniku(context["rocnik"], jen_verejne=False)
		context['temata_v_rocniku'] = verejna_temata(context["rocnik"])

		return context


class ProblemView(generic.DetailView):
	model = Problem

	def _je_clanek(self, problem):
		return problem.typ in [Problem.TYP_ORG_CLANEK, Problem.TYP_RES_CLANEK]

	def get_template_names(self, **kwargs):
		context = super(ProblemView, self).get_context_data(**kwargs)
		return ['seminar/archiv/problem_' + ('clanek.html' if self._je_clanek(context['problem']) else 'uloha_tema.html')]

	def get_context_data(self, **kwargs):
		context = super(ProblemView, self).get_context_data(**kwargs)
		if not context['problem'].verejne() and not self.request.user.is_staff:
			raise PermissionDenied()
		if context['problem'].typ == Problem.TYP_RES_CLANEK:
			context['reseni'] = Reseni.objects.filter(problem=context['problem']).select_related('resitel').order_by('resitel__prijmeni')
		return context


class VysledkyResitele(object):
	"""Pro daného řešitele ukládá počet bodů za jednotlivé úlohy a celkový
	počet bodů za číslo."""

	def __init__(self, jmeno, prijmeni):
		resitel_jmeno = jmeno
		resitel_prijmeni = prijmeni
		body = {}
		body_cislo = 0

	def body_za_cislo(self):
		return sum(body.values())

class CisloView(generic.DetailView):
	model = Cislo
	template_name = 'seminar/archiv/cislo.html'

       # Vlastni ziskavani objektu z databaze podle (Rocnik.rocnik)
	def get_object(self, queryset=None):
		if queryset is None:
			queryset = self.get_queryset()
		rocnik_arg = self.kwargs.get('rocnik')
		cislo_arg = self.kwargs.get('cislo')
		queryset = queryset.filter(rocnik__rocnik=rocnik_arg, cislo=cislo_arg)

		try:
			obj = queryset.get()
		except queryset.model.DoesNotExist:
			raise Http404(_("No %(verbose_name)s found matching the query") %
						{'verbose_name': queryset.model._meta.verbose_name})
		return obj

	# spočítá součet bodů získaných daným řešitelem za zadaný problém a všechny jeho podproblémy
	def __soucet_resitele_problemu(problem, resitel, soucet):
		# FIXME: správně je nadproblem_(typ problemu), ale to by bylo potřeba nějak 
		# zjistit, jaký typ nodu to vlastně je a aplikovat to ve volání funkce
	
		# sečteme body za daný problém přes všechna řešení daného problému 
		# od daného řešitele
		reseni_resitele = problem.hodnoceni_set.filter(reseni_resitele__contains=resitel)
		for r in reseni_resitele:
			soucet += r.body

		for p in problem.nadproblem_set: 
		# i přes jméno by to měla být množina jeho podproblémů
			soucet += __soucet_resitele_problemu(p, resitel, soucet)
		return soucet


	def vysledky_resitele_problemu(problem, resitel, cislo):
		return __soucet_resitele_problemu(problem, resitel, 0)	
		

	def get_context_data(self, **kwargs):
		context = super(CisloView, self).get_context_data(**kwargs)

		## TODO upravit dle nového modelu
		cislo = context['cislo']
		hodnoceni = cislo.hodnoceni_set	# hodnocení, která se vážou k danému číslu
		
		reseni = [h.reseni for h in hodnoceni]
		problemy = [h.problem for h in hodnoceni]
		problemy_set = set(problemy)	# chceme každý problém unikátně,
		problemy = (list(problemy_set)) # převedení na množinu a zpět to zaručí

		# hlavní problémy čísla 
		# (mají vlastní sloupeček ve výsledkovce, nemají nadproblém)
		hlavni_problemy = []
		for p in problemy:
			while not(p.nadproblem == None):
				p = nadproblem
			hlavni_problemy.append(p)

		# zunikátnění
		hlavni_problemy_set = set(hlavni_problemy)
		hlavni_problemy = list(hlavni_problemy_set)

		## TODO dostat pro tyto problémy součet v daném čísle pro daného řešitele
		## TODO možná chytřeji vybírat aktivní řešitele
		## chceme letos něco poslal
		aktivni_resitele = Resitel.objects.filter(
				rok_maturity__gte=context['rocnik'].druhy_rok())
				#.filter(hodnoceni_set__rocnik__eq=cislo_rocnik)
		radky_vysledkovky = []
		for ar in aktivni_resitele:
			vr = VysledkyResitele(ar.jmeno, ar.prijmeni)
			for h in hlavni_problemy: 
				body = vysledky_resitele_problemu(h, ar, cislo)
				vr.body[h.kod_v_rocniku] = body
				vr.body_cislo = vr.body_cislo + body 
			radky_vysledkovky.append(vr)

		## TODO: spočítat počet bodů řešitele v daném ročníku a seřadit je podle toho
		## TODO: možná použít tyto funkce i v RocnikVysledkovkaView (a umístit sem nebo tam)?
		

#		vysledky = VysledkyKCisluZaRocnik.objects.filter(cislo = context['cislo']).\
#			order_by('-body', 'resitel__prijmeni', 'resitel__jmeno')
#		reseni = Reseni.objects.filter(cislo_body = context['cislo']).select_related("resitel")

		# typy úloh, které se mají zobrazovat u čísla, tj. těch, které byly 
		# v čísle skutečně zadány
#		typy_skutecne_zadanych = [Problem.TYP_ULOHA, Problem.TYP_SERIAL, Problem.TYP_ORG_CLANEK]
#		v_cisle_zadane = Problem.objects.filter(cislo_zadani=context['cislo']).filter(typ__in=typy_skutecne_zadanych).order_by('kod')

#		resene_problemy = Problem.objects.filter(cislo_reseni=context['cislo']).filter(typ__in=typy_skutecne_zadanych).order_by('cislo_zadani__cislo', 'kod')
#
#		poradi_typu = {
#			Problem.TYP_ULOHA: 1,
#			Problem.TYP_SERIAL: 2,
#			Problem.TYP_ORG_CLANEK: 3,
#			Problem.TYP_TEMA: 4,
#			Problem.TYP_RES_CLANEK: 5
#		}
#		problemy = sorted(set(r.problem for r in reseni), key=lambda x:(poradi_typu[x.typ], x.kod_v_rocniku()))
#		#setridi problemy podle typu a poradi zadani
#		problem_index = {}
#		for i in range(len(problemy)):
#			#umoznuje zjistit index podle id problemu
#
#		vysledky_resitele = {}
#		vysledkovka = []
#
#		# doplníme některé údaje do řádků výsledkovky pro řešitele ve skupině
#		for poradi, v in zip(sloupec_s_poradim(vysledky), vysledky):
#			v.poradi = poradi
#			v.body_celkem_rocnik = v.body
#			v.body_celkem_odjakziva = VysledkyKCisluOdjakziva.objects.get(resitel=v.resitel, cislo=context['cislo']).body
#			v.resitel.rocnik = v.resitel.rocnik(v.cislo.rocnik)
#
#			# je tady '', aby se nezobrazovala 0, pokud se řešitel o řešení úlohy ani nepokusil
#			v.body_ulohy = [''] * len(problemy)
#
#			v.titul = v.resitel.get_titul(v.body_celkem_odjakziva)
#
#			body_cislo_q = VysledkyZaCislo.objects.filter(resitel=v.resitel, cislo=context['cislo'])
#			v.body_cislo = body_cislo_q[0].body if body_cislo_q else 0
#
#			vysledkovka.append(v)
#
#			# připravíme si odkaz na řádek, abychom do něj mohli doplnit body za jednotlivé úlohy
#			vysledky_resitele[v.resitel.id] = v
#
#		# za každé řešení doplníme k příslušnému řešiteli a úloze body
#		for r in reseni:
#			vysledky_resitele[r.resitel.id].body_ulohy[problem_index[r.problem.id]] = r.body
#
#		context['vysledkovka'] = vysledkovka
#		context['problemy'] = problemy
#		context['v_cisle_zadane'] = v_cisle_zadane
#		context['resene_problemy'] = resene_problemy
#		return context

class ArchivTemataView(generic.ListView):
	model = Problem
	template_name = 'seminar/archiv/temata.html'
	queryset = Tema.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')

### Generovani vysledkovky

#class CisloVysledkovkaView(CisloView):i
#	poradi | titul. jmeno prijmeni | ulohy | za cislo | celkem | odjakziva
#
#
#
#	model = Cislo
#	template_name = 'seminar/archiv/cislo_vysledkovka.tex'
#	#content_type = 'application/x-tex; charset=UTF8'
#	#umozni rovnou stahnout TeXovsky dokument
#	content_type = 'text/plain; charset=UTF8'
#	#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani
#
#class RocnikVysledkovkaView(RocnikView):
#	model = Rocnik
#	template_name = 'seminar/archiv/rocnik_vysledkovka.tex'
#	#content_type = 'application/x-tex; charset=UTF8'
#	#umozni rovnou stahnout TeXovsky dokument
#	content_type = 'text/plain; charset=UTF8'
#	#vypise na stranku textovy obsah vyTeXane vysledkovky k okopirovani

### Generovani obalek
class CisloObalkyStruct:
	rocnik = None
	cisla = None


# Vraci QuerySet aktualnich resitelu = nekdy neco poslali, ale jeste neodmaturovali
def aktualniResitele(rocnik):
	letos = Rocnik.objects.get(rocnik = rocnik)
	return Resitel.objects.filter(rok_maturity__gt = letos.prvni_rok)
#	# ALERT: pokud nekdo nema vypleny rok maturity, tak neni aktualni, protoze Karel Tesar a jini
#	return Resitel.objects.filter(Q(rok_maturity__gt = letos.prvni_rok)|Q(rok_maturity = None))

# Vraci QuerySet aktivnich resitelu =
# jeste neodmaturovali &&
# (pokud je aktualni cislo mensi nez 3, pak (letos || loni) neco poslali
# jinak letos neco poslali)
def aktivniResitele(rocnik,cislo):
	letos = CisloObalkyStruct()
	loni = CisloObalkyStruct()

	aktualni_resitele = aktualniResitele(rocnik)

	letos.rocnik = Rocnik.objects.get(rocnik = rocnik)
	loni.rocnik = Rocnik.objects.get(rocnik = int(rocnik)-1)
	letos.cisla = Cislo.objects.filter(rocnik=letos.rocnik,cislo__lte = cislo)
	loni.cisla = Cislo.objects.filter(rocnik=loni.rocnik)
	if int(cislo) > 3:
		problemy = Problem.objects.filter(cislo_zadani__in = letos.cisla)
	else:
		problemy = Problem.objects.filter(Q(cislo_zadani__in = letos.cisla)|Q(cislo_zadani__in = loni.cisla))
	resitele = aktualni_resitele.filter(reseni__in = Reseni.objects.filter(problem__in=problemy)).distinct()
	return resitele


def cisloObalkyView(request,rocnik,cislo):
	return obalkyView(request,aktivniResitele(rocnik,cislo))


def obalkyView(request,resitele):
	tex = render(request,'seminar/archiv/obalky.tex', {'resitele': resitele}).content

	tempdir = tempfile.mkdtemp()
	with open(tempdir+"/obalky.tex","wb") as texfile:
		texfile.write(tex)
	shutil.copy(os.path.join(settings.STATIC_ROOT, 'seminar/lisak.eps'),tempdir)
	subprocess.call(["pdflatex","obalky.tex"],cwd = tempdir)

	with open(tempdir+"/obalky.pdf","rb") as pdffile:
		response = HttpResponse(pdffile.read(),content_type='application/pdf')
	shutil.rmtree(tempdir)
	return response


def obalkovaniView(request, rocnik, cislo):
	rocnik = Rocnik.objects.get(rocnik=rocnik)
	cislo = Cislo.objects.get(rocnik=rocnik, cislo=cislo)

	reseni = (
		Reseni.objects.filter(cislo_body=cislo)
		.order_by(
			'resitel__prijmeni',
			'resitel__jmeno',
			'problem__typ',
			'problem__kod'
		)
	)

	problemy = sorted(set(r.problem for r in reseni), key=lambda p: (p.typ, p.kod))
	return render(
		request,
		'seminar/archiv/cislo_obalkovani.html',
		{'cislo': cislo, 'problemy': problemy, 'reseni': reseni}
	)

### Tituly

# TODO udelat neco jako get_objects_or_404
# FIXME: prepsat, aby nepouzivalo VysledkyK...
#def TitulyView(request, rocnik, cislo):
#	rocnik_obj = Rocnik.objects.get(rocnik = rocnik)
#	resitele = Resitel.objects.filter(rok_maturity__gte = rocnik_obj.prvni_rok)
#	cislo_obj = Cislo.objects.get(rocnik = rocnik_obj, cislo = cislo)
#
#	asciijmena = []
#	broken = False
#
#	for resitel in resitele:
#		try:
#			vys = VysledkyKCisluOdjakziva.objects.get(resitel = resitel, cislo = cislo_obj)
#			body = vys.body
#		except ObjectDoesNotExist:
#			body = 0
#		resitel.titul = resitel.get_titul(body)
#		resitel.ascii = unicodedata.normalize('NFKD',resitel.jmeno+resitel.prijmeni).encode("ascii","ignore").replace(" ","")
#		if resitel.ascii not in asciijmena:
#			asciijmena.append(resitel.ascii)
#		else:
#			broken = True
#
#	return render(request, 'seminar/archiv/tituly.tex',{'resitele': resitele,'broken':broken},content_type="text/plain")


### Soustredeni

class SoustredeniListView(generic.ListView):
	model = Soustredeni
	template_name = 'seminar/soustredeni/seznam_soustredeni.html'

class SoustredeniView(generic.DetailView):
	model = Soustredeni
	template_name = 'seminar/archiv/soustredeni.html'

def soustredeniObalkyView(request,soustredeni):
	soustredeni = get_object_or_404(Soustredeni,id = soustredeni)
	return obalkyView(request,soustredeni.ucastnici.all())


class SoustredeniUcastniciBaseView(generic.ListView):
	model = Soustredeni_Ucastnici

	def get_queryset(self):
		soustredeni = get_object_or_404(
			Soustredeni,
			pk=self.kwargs["soustredeni"]
		)
		return Soustredeni_Ucastnici.objects.filter(
			soustredeni=soustredeni).select_related('resitel')


class SoustredeniMailyUcastnikuView(SoustredeniUcastniciBaseView):
	"""Seznam e-mailů řešitelů oddělených čárkami"""
	model = Soustredeni_Ucastnici
	template_name = 'seminar/soustredeni/maily_ucastniku.txt'


class SoustredeniUcastniciView(SoustredeniUcastniciBaseView):
	"""HTML tabulka účastníků pro tisk"""
	model = Soustredeni_Ucastnici
	template_name = 'seminar/soustredeni/seznam_ucastniku.html'

def soustredeniUcastniciExportView(request,soustredeni):
	soustredeni = get_object_or_404(Soustredeni,id = soustredeni)
	ucastnici = Resitel.objects.filter(soustredeni=soustredeni)
	response = HttpResponse(content_type='text/csv')
	response['Content-Disposition'] = 'attachment; filename="ucastnici.csv"'

	writer = UnicodeWriter(response)
	writer.writerow(["jmeno", "prijmeni", "rok_maturity", "telefon", "email", "ulice", "mesto", "psc","stat"])
	for u in ucastnici:
		writer.writerow([u.jmeno, u.prijmeni, str(u.rok_maturity), u.telefon, u.email, u.ulice, u.mesto, u.psc, u.stat.name])
	return response


### Články

# FIXME: clanky jsou vsechny, pokud budou i neresitelske, tak se take zobrazi
class ClankyResitelView(generic.ListView):
	model = Problem
	template_name = 'seminar/clanky/resitelske_clanky.html'
	queryset = Clanek.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')

# FIXME: pokud chceme orgoclanky, tak nejak zavest do modelu a podle toho odkomentovat a upravit
#class ClankyOrganizatorView(generic.ListView)<F12>:
#	model = Problem
#	template_name = 'seminar/clanky/organizatorske_clanky.html'
#	queryset = Problem.objects.filter(stav=Problem.STAV_ZADANY).select_related('cislo_zadani__rocnik').order_by('-cislo_zadani__rocnik__rocnik', 'kod')


### Status

def StavDatabazeView(request):
#	nastaveni = Nastaveni.objects.get()
	problemy = utils.seznam_problemu()
	muzi = Resitel.objects.filter(pohlavi_muz=True)
	zeny = Resitel.objects.filter(pohlavi_muz=False)
	return render(request, 'seminar/stav_databaze.html',
			{
#				'nastaveni': nastaveni,
				'problemy': problemy,

				'resitele': Resitel.objects.all(),
				'muzi': muzi,
				'zeny': zeny,
				'jmena_muzu': utils.histogram([r.jmeno for r in muzi]),
				'jmena_zen': utils.histogram([r.jmeno for r in zeny]),
			})



@ensure_csrf_cookie
def LoginView(request):
	"""Pro přihlášení při nahrávání z texu"""
	q = request.POST
	# nastavení cookie csrftoken
	if not q:
		return JsonResponse({"ok": 1})

	if "username" in q:
		username = q["username"]
		password = q["password"]
		user = authenticate(username=username, password=password)
		if user is not None and user.is_staff:
			login(request, user)
			return JsonResponse({"ok": 1})
		else:
			return JsonResponse({"error": "Neplatné uživatelské jméno nebo heslo"})


@ensure_csrf_cookie
def texUploadView(request):

	def uloz_soubory(files, rocnik, cislo):
		for filename, f in files:
			path = os.path.join(
				settings.MEDIA_ROOT,
				settings.CISLO_IMG_DIR,
				rocnik,
				cislo,
				filename
			)

			adresar = os.path.dirname(path)
			if not os.path.exists(adresar):
				os.makedirs(adresar)

			with open(path, "wb+") as fout:
				for chunk in f.chunks():
					fout.write(chunk)

	q = request.POST
	# nastavení cookie csrftoken
	if not q:
		return JsonResponse({"ok": 1})

	# Odchytíme všechny výjimky a traceback pošleme v odpovědi
	try:
		meta = json.loads(q["meta"])
		html = q["html"]

		if meta["typ"] in ["uloha", "serial", "reseni", "tema"]:

			# Uložíme soubory
			if meta["typ"] != "reseni":
				c = meta["cislo"]
			else:
				# Řešení má nastavené číslo svojí úlohy, ale obrázky jsou
				# ukládány do čísla, kde řešení vyšlo
				c = meta["cislo_reseni"]

			# Zjistíme typ ukládaného problému
			typy = {
				"uloha": Problem.TYP_ULOHA,
				"serial": Problem.TYP_SERIAL,
				"reseni": Problem.TYP_ULOHA,
				"tema": Problem.TYP_TEMA,
			}
			problem_typ = typy[meta["typ"]]

			# Pokud už problém existuje, vytáhneme jej z db a upravíme
			# Pokud neexistuje, vytvoříme jej jedině pokud je to vynucené

			# Pokud ročník/číslo ještě neexistuje, vyhodí to výjimku ->
			# číslo/ročník se musí založit ručně v adminu
			rocnik = Rocnik.objects.get(rocnik=meta["rocnik"])
			cislo = Cislo.objects.get(rocnik=rocnik, cislo=meta["cislo"])

			existujici = Problem.objects.filter(
				typ=problem_typ,
				stav=Problem.STAV_ZADANY,
				cislo_zadani=cislo,
				kod=meta["kod"]
			)

			problem = None
			if existujici:
				problem = existujici[0]
			elif "vytvor" in q:
				# vytvoříme nový
				problem = Problem(
					typ=problem_typ,
					stav=Problem.STAV_ZADANY,
					kod=meta["kod"],
					cislo_zadani=cislo
				)
			else:
				return JsonResponse({
					"error": "Problém neexistuje: {} {}.{} kód {}".format(
						meta["typ"], meta["rocnik"], meta["cislo"], meta["kod"]
					)
				})

			uloz_soubory(request.FILES.items(), meta["rocnik"], c)

			if meta["typ"] == "reseni":
				problem.text_reseni = html

				# Pokud ročník/číslo ještě neexistuje, vyhodí to výjimku ->
				# číslo/ročník se musí založit ručně v adminu
				problem.cislo_reseni = Cislo.objects.get(
					rocnik=rocnik,
					cislo=meta["cislo_reseni"]
				)
				# při nahrávání řešení už původní zadání atd. neměníme
			else:
				problem.text_zadani = html
				problem.nazev = meta["nazev"]
				if meta["typ"] != "tema":
					problem.body = meta["body"]

			problem.save()
			cislo.faze = cislo.FAZE_NAHRANO
			cislo.save()

			# Vrátíme id dané úlohy, aby se k ní dala případně připojit pohádka
			return JsonResponse({"db_id": problem.id})

		elif meta["typ"] == "pohadka":
			uloha = Problem.objects.get(typ=Problem.TYP_ULOHA, pk=meta["uloha"])

			# Pokud už příslušná pohádka existuje, jen ji upravíme
			existujici = Pohadka.objects.filter(uloha=uloha, pred=meta["pred"])
			pohadka = None
			if existujici:
				pohadka = existujici[0]
			else:
				pohadka = Pohadka(uloha=uloha, pred=meta["pred"])
			pohadka.text = q["html"]
			pohadka.save()

			return JsonResponse({"db_id": pohadka.id})

	except Exception as e:
		# Pošleme zpátky traceback, ať uživatel ví, v čem je problém
		tb = "".join(traceback.format_exception(type(e), e, sys.exc_info()[2]))
		return JsonResponse({"error": tb})


def texDownloadView(request, rocnik, cislo):
	"""View posílající JSON se zadanými a řešenými problémy pro založení čísla
	"""
	cislo = Cislo.objects.get(rocnik__rocnik=rocnik, cislo=cislo)
	if cislo.faze == cislo.FAZE_NAHRANO:
		# obsah byl nahrán z TeXu na web, už je příliš složitý
		return JsonResponse(
			{"error": "Obsah čísla už byl nahrán z TeXu na web."}
		)

	zadane = Problem.objects.filter(
		cislo_zadani=cislo,
		stav=Problem.STAV_ZADANY
	)
	resene = Problem.objects.filter(
		cislo_reseni=cislo,
		stav=Problem.STAV_ZADANY,
		typ=Problem.TYP_ULOHA
	)
	pred_pohadky = Pohadka.objects.filter(uloha__cislo_zadani=cislo, pred=True)
	po_pohadky = Pohadka.objects.filter(uloha__cislo_zadani=cislo, pred=False)

	response = {
		"zadane": [
			{
				"nazev": p.nazev,
				"typ": p.typ,
				"kod": p.kod,
				"body": p.body,
				"zadani": p.text_zadani,
				"pred_pohadky": [x.text for x in pred_pohadky.filter(uloha=p)],
				"po_pohadky": [x.text for x in po_pohadky.filter(uloha=p)],
			} for p in zadane
		],
		"resene": [
			{
				"nazev": p.nazev,
				"typ": p.typ,
				"kod": p.kod,
				"body": p.body,
				"zadani": p.text_zadani,
				"reseni": p.text_reseni,
				"cislo_zadani": p.cislo_zadani.cislo,
			} for p in resene
		],
	}

	cislo.faze = Cislo.FAZE_TEX
	cislo.save()
	return JsonResponse(response)

## Formulare

def get_name(request):
	# if this is a POST request we need to process the form data
	if request.method == 'POST':
		# create a form instance and populate it with data from the request:
		form = NameForm(request.POST)
		# check whether it's valid:
		if form.is_valid():
			# process the data in form.cleaned_data as required
			# ...
			# redirect to a new URL:
			return HttpResponseRedirect('/thanks/')

	# if a GET (or any other method) we'll create a blank form
	else:
		form = NameForm()

	return render(request, 'seminar/prihlaska.html', {'form': form})

# Ceka na autocomplete v3
# class OrganizatorAutocomplete(autocomplete.Select2QuerySetView):
# 	def get_queryset(self):
# 		if not self.request.user.is_authenticated():
# 			return Organizator.objects.none()
#
# 		qs = aktivniOrganizatori()
#
# 		if self.q:
# 			if self.q[0] == "!":
# 				qs = Organizator.objects.all()
# 				query = self.q[1:]
# 			else:
# 				query = self.q
# 			qs = qs.filter(
# 				Q(prezdivka__isstartswith=query)|
# 				Q(user__first_name__isstartswith=query)|
# 				Q(user__last_name__isstartswith=query))
#
# 		return qs