# -*- coding: utf-8 -*-

import datetime

from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group
from pytz import timezone
import random
import lorem
import django.contrib.auth
from django.db import transaction
import unidecode
import logging

from korektury.testutils import create_test_pdf
from seminar.models import Skola, Resitel, Rocnik, Cislo, Deadline, Problem, Reseni, PrilohaReseni, Nastaveni, Soustredeni, Soustredeni_Ucastnici, Soustredeni_Organizatori, Osoba, Organizator, Prijemce, Tema, Uloha, Konfera, TextNode, UlohaVzorakNode, RocnikNode, CisloNode, TemaVCisleNode, Text, Hodnoceni, UlohaZadaniNode, Novinky, TreeNode
import seminar.models as m

from django.contrib.flatpages.models import FlatPage
from django.contrib.sites.models import Site
from treenode.treelib import all_children, insert_last_child, all_children_of_type, create_node_after


User = django.contrib.auth.get_user_model()
zlinska = None # tohle bude speciální škola, které později dodáme kontaktní osobu

logger = logging.getLogger(__name__)

# testuje unikátnost vygenerovaného jména
def __unikatni_jmeno(osoby, jmeno, prijmeni):
	for os in osoby:
		if os.jmeno == jmeno and os.prijmeni == prijmeni:
			return 0
	else: return 1

def gen_osoby(rnd, size):
	logger.info('Generuji osoby (size={})...'.format(size))

	jmena_m = ['Aleš', 'Tomáš', 'Martin', 'Jakub', 'Petr', 'Lukáš', 'Cyril', 'Pavel Karel']
	jmena_f = ['Eva', 'Karolína', 'Zuzana', 'Sylvie', 'Iva', 'Jana', 'Marie',
		'Marta Iva', 'Shu Shan']
	prijmeni_m = ['Novotný', 'Svoboda', 'Pecha', 'Kořen', 'Holan', 'Uhlíř', 'Chytráček',
			'Pokora', 'Koch', 'Szegedy', 'Rudý', "von Neumann", "d'Este"]
	prijmeni_f = ['Novotná', 'Svobodová', 'Machová', 'Zelená', 'Yu-Xin', 'Mlsná', 'Dubná',
			'Mrkvová', 'Suchá', 'Lovelace', 'Holcová', 'Rui', "Nováčková Tydlitátová"]
	prezdivky = ['Kaki', 'Hurdur', 'Maracuja', 'Bobbo', "", "", "", "", "",
			"", "", 'Riki', 'Sapa', "", '', '---', 'Koko']
	domain = ['example.com', 'dolujeme.eu', 'mff.cuni.cz', 'strcprstskrzkrk.cz',
			'british.co.uk', 'splachni.to', 'haha.org']
	seznam_ulic = ['Krátká', 'Vlhká', 'Jungmanova', '17. listopadu', '4. října', 'Roztocká',
			'Forstova', 'Generála Františka Janouška', 'Náměstí Války',
			'Svratecké náměstí', 'Zelená lhota', 'Z Plynu', 'K Jezeru', 'U Kocourkova',
			'Uštěpačná', 'Ostrorepská', 'Zubří']
	seznam_mest = ['Praha', 'Brno', 'Ostrava', 'Horní Jelení', 'Dolní Zábrdovice', 'Prdelkov',
			'Stará myslivna', 'Kocourkov', 'Šalingrad', 'Medvědí hora', 'Basilej',
			'Unterschiedlich', 'Old York', 'Lancastershire', 'Vóloďháza']

	osoby = []
	# 30 je náhodná konstanta, size je použité na víc místech a
	# říká, jak velká asi chceme testovací data
	for i in range(30 * size):
		pohlavi = rnd.randint(0,1)
		jmeno = rnd.choice([jmena_m, jmena_f][pohlavi])
		prijmeni = rnd.choice([prijmeni_m, prijmeni_f][pohlavi])
		pokusy = 0
		max_pokusy = 120*size
		while (not __unikatni_jmeno and pokusy < max_pokusy):
		# pokud jméno a příjmení není unikátní, zkoušíme generovat nová
		# do daného limitu (abychom se nezacyklili do nekonečna při málo jménech a příjmeních
		# ze kterých se generuje)
			jmeno = rnd.choice([jmena_m, jmena_f][pohlavi])
			prijmeni = rnd.choice([prijmeni_m, prijmeni_f][pohlavi])
			pokusy = pokusy + 1
		if pokusy >= max_pokusy:
			print("Chyba, na danou velikost testovacích dat příliš málo možných"
				" jmen a příjmení")
			exit()
		prezdivka = rnd.choice(prezdivky)
		email = "@".join([unidecode.unidecode(jmeno), rnd.choice(domain)])
		telefon = "".join([str(rnd.choice([k for k in range(10)])) for i in range(9)])
		narozeni = datetime.date(rnd.randint(1980, datetime.datetime.now().year), 
				rnd.randint(1, 12), rnd.randint(1, 28))
		ulic = rnd.choice(seznam_ulic)
		cp = rnd.randint(1, 99)
		ulice = " ".join([ulic, str(cp)])
		mesto = rnd.choice(seznam_mest)
		psc = "".join([str(rnd.choice([k for k in range(10)])) for i in range(5)])

		osoby.append(Osoba.objects.create(jmeno = jmeno, prijmeni = prijmeni,
				prezdivka = prezdivka, pohlavi_muz = pohlavi, email = email,
				telefon = telefon, datum_narozeni = narozeni, ulice = ulice,
				mesto = mesto, psc = psc,
				datum_registrace = datetime.date(rnd.randint(2019, 2029),
					rnd.randint(1, 12), rnd.randint(1, 28))))
		#TODO pridat foto male a velke. Jak?
				# Pavel tvrdí, že to necháme a přidáme až do adminu

	return osoby



def gen_skoly(): #TODO někdy to přepsat, aby jich bylo více
	logger.info('Generuji školy...')

	skoly = []
	prvnizs = Skola.objects.create(mesto='Praha', stat='CZ', psc='101 00',
		ulice='Krátká 5', nazev='První ZŠ', je_zs=True, je_ss=False)
	skoly.append(prvnizs)
	skoly.append(Skola.objects.create(mesto='Praha', stat='CZ', psc='101 00',
		ulice='Krátká 5', nazev='První SŠ', je_zs=False, je_ss=True))
	skoly.append(Skola.objects.create(mesto='Praha', stat='CZ', psc='102 00',
		ulice='Dlouhá 5', nazev='Druhá SŠ', je_zs=False, je_ss=True))
	skoly.append(Skola.objects.create(mesto='Praha', stat='CZ', psc='103 00',
		ulice='Široká 3', nazev='Třetí SŠ a ZŠ', je_zs=True, je_ss=True))
	skoly.append(Skola.objects.create(mesto='Ostrava', stat='CZ', psc='700 00',
		ulice='Hluboká 42', nazev='Hutní gympl', je_zs=False, je_ss=True))
	skoly.append(Skola.objects.create(mesto='Humenné', stat='SK', psc='012 34',
		ulice='Pltká 1', nazev='Sredná škuola', je_zs=False, je_ss=True))
	global zlinska
	zlinska = Skola.objects.create(mesto = 'Zlín', stat='CZ', psc='76001',
		ulice='náměstí T.G. Masaryka 2734-9',
		nazev='Gymnázium a Střední jazyková škola s právem SJZ',
		kratky_nazev="GaSJŠspSJZ", je_zs=True, je_ss=True)
	skoly.append(zlinska)
	return skoly

def gen_resitele(rnd, osoby, skoly):
	logger.info('Generuji řešitele...')

	resitele = []
	x = 0
	resitel_perm = Permission.objects.filter(codename__exact='resitel').first()
	resitel_group = Group.objects.filter(name__exact='resitel').first()
	for os in osoby:
		rand = rnd.randint(0, 8)
		if not (rand % 8 == 0):
			if not os.user:
				if x:
					user = User.objects.create_user(username='r'+str(x), email=os.email, password='r')
				else:
					user = User.objects.create_user(username='r', email=os.email, password='r')
				x += 1
				os.user = user
				os.save()
				os.user.user_permissions.add(resitel_perm)
				os.user.groups.add(resitel_group)
			resitele.append(Resitel.objects.create(osoba=os, skola=rnd.choice(skoly),
				rok_maturity=os.datum_narozeni.year + rnd.randint(18, 21),
				zasilat=rnd.choice(Resitel.ZASILAT_CHOICES)[0]))
	return resitele

def gen_prijemci(rnd, osoby, kolik=10):
	logger.info('Generuji příjemce (kolik={})...'.format(kolik))
	prijemci = []
	for i in rnd.sample(osoby, kolik):
		prijemci.append(Prijemce.objects.create(osoba=i))
	return prijemci

def gen_organizatori(rnd, osoby, last_rocnik):
	logger.info('Generuji organizátory...')
	organizatori = []

	
	seznam_konicku = ["vařím", "jezdím na kole", "řeším diferenciální rovnice", "koukám z okna",
			"tancuji", "programuji", "jezdím vlakem", "nedělám nic"]
	seznam_oboru = ["matematiku", "matematiku", "matematiku", "fyziku", "literaturu",
			"informatiku", "informatiku", "běhání dokolečka"]

	x = 0
	org_perm = Permission.objects.filter(codename__exact='org').first()
	org_group = Group.objects.filter(name__exact='org').first()
	for os in osoby:
		rand = rnd.randint(0, 8)
		if (rand % 8 == 0):
			pusobnost = rnd.randint(1, last_rocnik)
			od = datetime.datetime(
				year=1993 + pusobnost,
				month=rnd.randint(1, 12),
				day=rnd.randint(1, 28),
				tzinfo=timezone('CET'),
				)
			do = datetime.datetime(
				year=od.year + rnd.randint(1, 6),
				month=rnd.randint(1, 12),
				day=rnd.randint(1, 28),
				tzinfo=timezone('CET'),
				)
			#aktualni organizatori jeste nemaji vyplnene organizuje_do

			#popis orga
			konicek1 = rnd.choice(seznam_konicku)
			konicek2 = rnd.choice(seznam_konicku)
			obor = rnd.choice(seznam_oboru)
			popis_orga = "Ve volném čase " + konicek1 + " a také " + konicek2 + ". Studuji " + obor + " a moc mě to baví."

			if do.year > datetime.datetime.now().year:
				do = None
			if not os.user:
				if x:
					user = User.objects.create_user(username='o'+str(x), email=os.email, password='o')
				else:
					user = User.objects.create_user(username='o', email=os.email, password='o')
				x += 1
				os.user = user
				os.save()
				os.user.user_permissions.add(org_perm)
				os.user.groups.add(org_group)
				os.user.is_staff = True
				os.user.save()
			organizatori.append(Organizator.objects.create(osoba=os,
				organizuje_od=od, organizuje_do=do, strucny_popis_organizatora = popis_orga))
	return organizatori

def gen_zadani_ulohy(rnd, cisla, organizatori, pocet_oboru, poradi_cisla, poradi_problemu):
	
	# Proměnné pro náhodné generování názvů a zadání.
	jaka = ["Šachová", "Černá", "Větrná", "Dlouhá", "Křehká", "Rychlá",
		"Zákeřná", "Fyzikální"]
	co = ["kostka", "smršť", "díra", "zrada", "toulka", "tyč",
		"úloha", "blecha"]
	sloveso = ["Najděte", "Spočítejte", "Zapište", "Změřte", "Odhadněte"]
	koho = ["délku", "počet", "množství", "dílky"]
	ceho = ["všech", "správných", "konstatních", "zelených"]
	jmeno = ["řešení", "tahů", "čísel", "kalhot", "koulí", "hadů"]
	kde = ["na zemi", "ve vesmíru", "ve vzduchu", "na šňůře", "v letadle"]
	obory = ["M", "F", "I", "O", "B"]

	p = Uloha.objects.create(
		# atributy třídy Problem
		nazev=" ".join([rnd.choice(jaka), rnd.choice(co)]),
		stav=Problem.STAV_ZADANY,
		zamereni=rnd.sample(obory, pocet_oboru),
		autor=rnd.choice(organizatori),
		garant=rnd.choice(organizatori),
		kod=str(poradi_problemu),
		# atributy třídy Uloha
		cislo_zadani=cisla[poradi_cisla-2-1],
		cislo_reseni=cisla[poradi_cisla-1],
		cislo_deadline=cisla[poradi_cisla-1],
		max_body = rnd.randint(1, 8)
	)

	text = " ".join(
		[rnd.choice(sloveso),
		rnd.choice(koho),
		rnd.choice(ceho),
		rnd.choice(jmeno),
		rnd.choice(kde)]
		)
	text_zadani = Text.objects.create(
		na_web = text,
		do_cisla = text,
	)
	zad = TextNode.objects.create(text = text_zadani, root = p.cislo_zadani.rocnik.rocniknode)
	uloha_zadani = UlohaZadaniNode.objects.create(uloha = p, first_child = zad, root = p.cislo_zadani.rocnik.rocniknode)
	p.ulohazadaninode = uloha_zadani
	otec_syn(cisla[poradi_cisla-2-1].cislonode, uloha_zadani)

	return p

def gen_vzoroveho_reseni_ulohy(rnd, organizatori, uloha, pocet_opravovatelu):
	reseni = ["to je přece jasné", "triviální", "omlouváme se,"
		"otevřený problém", "neřešitelné", "triviálně triviální",
		"použitím věty z prvního semestru na matfyzu",
		"jednoduše pomocí látky z druhého semestru na matfyzu",
		"netriviální aplikace diferenciálních rovnic", "zadání je vnitřně"
		"sporné", "nepopsatelně jednoduché", "pokud jste na to nepřišli,"
		"tak jste fakt hloupí"]

	# Generování vzorového řešení.
	obsah = rnd.choice(reseni)
	text_vzoraku = Text.objects.create(
		na_web = obsah,
		do_cisla = obsah
	)
	vzorak = TextNode.objects.create(text = text_vzoraku, root = uloha.cislo_zadani.rocnik.rocniknode)
	uloha_vzorak = UlohaVzorakNode.objects.create(uloha = uloha, first_child = vzorak, root = uloha.cislo_zadani.rocnik.rocniknode)
	uloha.ulohavzoraknode = uloha_vzorak

	uloha.opravovatele.set(rnd.sample(organizatori, pocet_opravovatelu))
	uloha.save()
	return uloha_vzorak

def gen_reseni_ulohy(rnd, cisla, uloha, pocet_resitelu, poradi_cisla, resitele_cisla, resitele):
	
	pocet_reseni = rnd.randint(pocet_resitelu//4, pocet_resitelu * 4)
	# generujeme náhodný počet řešení vzhledem k počtu řešitelů čísla
	for _ in range(pocet_reseni):
		#print("Generuji {}-té řešení".format(reseni))
		if rnd.randint(1, 10) == 1:
		# cca desetina řešení od více řešitelů
			res_vyber = rnd.sample(resitele_cisla, 
				rnd.randint(2, 5))
		else:
			res_vyber = rnd.sample(resitele_cisla, 1)
		if resitele[0] in res_vyber: # speciální řešitel, který nemá žádné body
			res_vyber.remove(resitele[0])

		# Vytvoření řešení.
		if uloha.cislo_zadani.zlomovy_deadline_pro_papirove_cislo() is not None:
			# combine, abychom dostali plný čas a ne jen datum
			cas_doruceni = uloha.cislo_zadani.deadline_v_cisle.first().deadline - datetime.timedelta(days=random.randint(0, 40)) - datetime.timedelta(minutes=random.randint(0, 60*24))
			# astimezone, protože jinak vyhazuje warning o nenastavené TZ
			res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0], cas_doruceni=cas_doruceni.astimezone(datetime.timezone.utc))
		else:
			res = Reseni.objects.create(forma=rnd.choice(Reseni.FORMA_CHOICES)[0])
		# Problém a řešitele přiřadíme později, ManyToManyField
		# se nedá vyplnit v create().
		res.resitele.set(res_vyber)
		res.save()
		
		# Vytvoření hodnocení.
		hod = Hodnoceni.objects.create(
			body=rnd.randint(0, uloha.max_body),
			cislo_body=cisla[poradi_cisla - 1],
			reseni=res,
			problem=uloha
		)
	return

def gen_ulohy_do_cisla(rnd, organizatori, resitele, rocnik_cisla, rocniky, size):
	logger.info('Generuji úlohy do čísla (size={})...'.format(size))

	k = 0
	for rocnik in rocniky:
		k += 1
		print("Generuji {}. číslo.".format(k))
		cisla = rocnik_cisla[k - 1]
		for ci in range(3, len(cisla) + 1): # pro všechna čísla
			resitele_size = round(7/8 * 30 * size) # očekáváný celkový počet řešitelů
			poc_res = rnd.randint(resitele_size//8, resitele_size//4)
 			# dané číslo řeší něco mezi osminou a čtvrtinou všech řešitelů
			# (náhodná hausnumera, možno změnit)
			# účelem je, aby se řešení generovala z menší množiny řešitelů a tedy
			# bylo více řešení od jednoho řešitele daného čísla
			resitele_cisla = rnd.sample(resitele, poc_res)
			for pi in range(1, ((size + 1) // 2) + 1): # počet problémů

				poc_op = rnd.randint(1, 4) # počet opravovatelů
				poc_oboru = rnd.randint(1, 2)
				
				# Generování zadání úlohy a UlohaZadaniNode, 
				# přivěšení pod dané číslo
				p = gen_zadani_ulohy(rnd, cisla, organizatori, poc_oboru, ci, pi)	
				# Generování vzorového řešení
				uloha_vzorak = gen_vzoroveho_reseni_ulohy(rnd, organizatori, 
					p, poc_op)
				insert_last_child(cisla[ci-1].cislonode, uloha_vzorak)

				# Generování řešení a hodnocení k úloze
				gen_reseni_ulohy(rnd, cisla, p, poc_res, ci, 
					resitele_cisla, resitele) 

	return

def gen_soustredeni(rnd, resitele, organizatori):
	logger.info('Generuji soustředění...')

	soustredeni = []
	for _ in range(1, 10): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?)
		datum_zacatku=datetime.date(rnd.randint(2000, 2020), rnd.randint(1, 12), rnd.randint(1, 28))
		working_sous = Soustredeni.objects.create(
			rocnik=Rocnik.objects.order_by('?').first(),
			verejne_db=rnd.choice([True, False]),
			misto=rnd.choice(['Kremrolovice', 'Indiánov', 'U zmzliny', 'Vafláreň', 'Větrník', 'Horní Rakvička', 'Dolní cheesecake']),
			typ=rnd.choice(['jarni', 'podzimni', 'vikend']),
			datum_zacatku=datum_zacatku,
			datum_konce=datum_zacatku + datetime.timedelta(days=7))
		ucastnici = rnd.sample(resitele, min(len(resitele), 20))
		working_sous.ucastnici.set(ucastnici)
		#for res in rnd.sample(resitele, min(len(resitele), 20)):
		#	Soustredeni_Ucastnici.objects.create(resitel=res, soutredeni=working_sous)
		orgove_vyber = rnd.sample(organizatori, min(len(organizatori), 20))
		working_sous.organizatori.set(orgove_vyber)
		#for org in rnd.sample(organizatori, min(len(organizatori), 20)):
		#	Soustredeni_Organizatori.objects.create(organizator=org, soutredeni=working_sous)
		working_sous.save()
		soustredeni.append(working_sous)
	return soustredeni

def gen_rocniky(last_rocnik, size):
	logger.info('Generuji ročníky (size={})...'.format(size))

	rocniky = []
	node = None
	for ri in range(min(last_rocnik - size, 1), last_rocnik + 1):
		rocnik = Rocnik.objects.create(prvni_rok = 1993 + ri, rocnik = ri)
		node2 = RocnikNode.objects.create(rocnik = rocnik, succ = node)
		rocnik.save()
		node = node2
		rocniky.append(rocnik)
	return rocniky

def gen_konfery(size, rnd, organizatori, resitele, soustredeni):
	logger.info('Generuji konfery (size={})...'.format(size))

	konfery = []
	for _ in range(1, size): #FIXME Tu range si změňte jak chcete, nevím, co přesně znamená size (asi Anet?)
		# Anet: size je parametr udávající velikost testovacích dat a dá se pomocí ní škálovat,
		# kolik dat se nageneruje
		konfera = Konfera.objects.create(
			nazev=rnd.choice(['Pozorování', 'Zkoumání', 'Modelování', 'Počítání', 'Zkoušení']) + rnd.choice([' vlastností', ' jevů', ' charakteristik']) + rnd.choice([' vektorových prostorů', ' kinetické terorie látek', ' molekulární biologie', ' syntentických stromů']),
			anotace=lorem.paragraph(),
			abstrakt=lorem.paragraph(),
			garant=rnd.choice(organizatori),
			soustredeni=rnd.choice(soustredeni),
			typ_prezentace=rnd.choice(['veletrh', 'prezentace']))
		ucastnici_sous = list(konfera.soustredeni.ucastnici.all())
		ucastnici = rnd.sample(ucastnici_sous, min(len(ucastnici_sous), rnd.randint(3, 6)))
		konfera.ucastnici.set(ucastnici)
		#for res in rnd.sample(ucastnici, min(len(ucastnici), rnd.randint(3, 6))):
		#	Konfery_Ucastnici.objects.create(resitel=res, konfera=konfera)
		konfera.save()
		konfery.append(konfera)
	return konfery

def gen_cisla(rnd, rocniky):
	logger.info('Generuji čísla...')

	rocnik_cisla = []
	for rocnik in rocniky:
		otec = True
		cisla = []
		cisel = rnd.randint(4, 8)
		node = None
		for ci in range(1, cisel + 1):
			# první číslo vydáváme typicky okolo prázdnin
			# (ci - 1)*2 zaručuje první číslo v červnu a všechna
			# další po dvou měsících (což je rozumná aproximace)
			mesic_vydani = (ci - 1)*2 + 6
			# celociselné dělení mi řekne, jestli to je první nebo druhý rok ročníku
			vydano = datetime.date(rocnik.prvni_rok + mesic_vydani // 12,
				(mesic_vydani - 1) % 12 + 1,
				rnd.randint(1, 28))
			deadline = datetime.date(rocnik.prvni_rok + (mesic_vydani + 2) // 12,
				(mesic_vydani + 1) % 12 + 1,
				rnd.randint(1, 28))

			cislo = Cislo.objects.create(
				rocnik = rocnik,
				poradi = str(ci), 
				datum_vydani=vydano,
				verejne_db=True,
			)
			node2 = CisloNode.objects.get(cislo = cislo)
			node2.succ = node
			node2.root = rocnik.rocniknode
			cislo.save()
			deadline = Deadline.objects.create(
				cislo=cislo,
				deadline=deadline,
				typ=Deadline.TYP_CISLA,
				verejna_vysledkovka=True,
			)
			deadline.save()
			node = node2
			if otec:
				otec = False
				rocnik.rocniknode.first_child = node
				rocnik.save()

			cisla.append(cislo)
		rocnik_cisla.append(cisla)
	return rocnik_cisla

def add_first_child(node, child):
	node.first_child = child
	node.save()
	return

def get_text():
	odstavec = lorem.paragraph()
	return Text.objects.create(na_web = odstavec, do_cisla = odstavec)	

def gen_dlouhe_tema(rnd, organizatori, rocnik, nazev, obor, kod):
	tema = Tema.objects.create(
                nazev=nazev,
                stav=Problem.STAV_ZADANY,
                zamereni="M",
                autor=rnd.choice(organizatori),
                garant=rnd.choice(organizatori),
                kod=str(kod),
                tema_typ=rnd.choice(Tema.TEMA_CHOICES)[0],
                rocnik=rocnik,
                abstrakt = lorem.paragraph() 
		)
	
	# Generování struktury k tématu
	cisla = sorted(rocnik.cisla.all(), key=lambda cislo: cislo.poradi)
	for cislo in cisla:
		# Přidáme TemaVCisleNode do daného čísla
		cislo_node = cislo.cislonode	
		tema_cislo_node = TemaVCisleNode.objects.create(tema = tema, root = cislo_node.root)
		insert_last_child(cislo_node, tema_cislo_node)
		
		# Přidávání obsahu do čísla
		cast_node = m.CastNode.objects.create(nadpis = "Příspěvek k číslu {}".format(cislo.kod), root=cislo_node.root)
		add_first_child(tema_cislo_node, cast_node)
	
		text_node = TextNode.objects.create(text = get_text(), root=cislo_node.root)
		add_first_child(cast_node, text_node)

		cast_node2 = m.CastNode.objects.create(nadpis = "První podproblém", root=cislo_node.root)
		add_first_child(text_node, cast_node2)
		
		text_node2 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
		add_first_child(cast_node2, text_node2)
		
		cast_node3 = m.CastNode.objects.create(nadpis = "Druhý podproblém", root=cislo_node.root)
		add_first_child(text_node2, cast_node3)

		text_node3 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
		add_first_child(cast_node3, text_node3)

		cast_node4 = m.CastNode.objects.create(nadpis = "Třetí podproblém", root=cislo_node.root)
		add_first_child(text_node3, cast_node4)	

		text_node4 = TextNode.objects.create(text = get_text(), root=cislo_node.root)
		add_first_child(cast_node3, text_node4)
		
		cast_node3a = m.CastNode.objects.create(nadpis = "Podproblém paralelní s "
					"druhým podproblémem", root=cislo_node.root)
		cast_node3.succ = cast_node3a
		cast_node3.save()

		text_node3a = TextNode.objects.create(text = get_text(), root=cislo_node.root)
		add_first_child(cast_node3a, text_node3a)

		# Občas přidáme mezičíslo
		if rnd.randint(1, 3) == 1:
			create_node_after(cislo_node, m.MezicisloNode, root=cislo_node.root)
			mezicislo_node = cislo_node.succ
	
			cast_node_mezicislo = m.CastNode.objects.create(
					nadpis = "Příspěvek k mezičíslu".format(cislo.kod), root=cislo_node.root)
			add_first_child(mezicislo_node, cast_node_mezicislo)

			odstavec = lorem.paragraph()
			text_mezicislo = Text.objects.create(na_web = odstavec, do_cisla = odstavec)
			text_node_mezicislo = TextNode.objects.create(text = text_mezicislo, root=cislo_node.root)
			add_first_child(cast_node_mezicislo, text_node_mezicislo)

	return tema

def gen_temata(rnd, rocniky, rocnik_cisla, organizatori):
	logger.info('Generuji témata...')

	jake = ["Hravé", "Fyzikální", "Nejlepší", "Totálně masakrální",
					"Šokující", "Magnetické", "Modré", "Překvapivé",
					"Plasmatické", "Novoroční"]
	co = ["téma", "záření", "stavení", "jiskření", "jelito",
					"drama", "kuře", "moře", "klání", "proudění", "čekání"]
	poc_oboru = rnd.randint(1, 2)

	rocnik_temata = []
	# Věříme, že rocnik_cisla je pole polí čísel podle ročníků, tak si necháme dát 
	# vždycky jeden ročník a k němu příslušná čísla.
	for rocnik, cisla in zip(rocniky, rocnik_cisla):
		kod = 1
		letosni_temata = []
		# Do každého ročníku vymyslíme tři (zatím) témata, v každém z prvních čísel jedno
		for zacatek_tematu in range(1, 3):
			# Vygenerujeme téma
			t = Tema.objects.create(
				# atributy třídy Problem
				nazev=" ".join([rnd.choice(jake), rnd.choice(co)]),
				stav=Problem.STAV_ZADANY,
				zamereni=rnd.sample(["M", "F", "I", "O", "B"], poc_oboru),
				autor=rnd.choice(organizatori),
				garant=rnd.choice(organizatori),
				kod=str(kod),
				# atributy třídy Téma
				tema_typ=rnd.choice(Tema.TEMA_CHOICES)[0],
				rocnik=rocnik,
				abstrakt = "Abstrakt tematka {}".format(kod)
			)
			kod += 1

			# Vymyslíme, kdy skončí
			konec_tematu = min(rnd.randint(zacatek_tematu, 7), len(cisla))

			# Vyrobíme TemaVCisleNody pro obsah
			for i in range(zacatek_tematu, konec_tematu+1):
				node = TemaVCisleNode.objects.create(tema = t,root=rocnik.rocniknode)
				# FIXME: Není to off-by-one?
				otec = cisla[i-1].cislonode
				otec_syn(otec, node)

			# Vymyslíme, kdo to bude opravovat
			poc_opravovatelu = rnd.randint(1, 3)
			t.opravovatele.set(rnd.sample(organizatori, poc_opravovatelu))

			# Uložíme všechno
			t.save()
			letosni_temata.append((zacatek_tematu, konec_tematu, t))
		rocnik_temata.append(letosni_temata)
	return rocnik_temata

def gen_ulohy_tematu(rnd, organizatori, resitele, tema, kod, cislo, cislo_se_vzorakem):
	""" Generování úlohy k danému tématu. """
	
	# Proměnné pro náhodné generování názvů a zadání.
	jaka = ["Šachová", "Černá", "Větrná", "Dlouhá", "Křehká", "Rychlá",
		"Zákeřná", "Fyzikální"]
	co = ["kostka", "smršť", "díra", "zrada", "toulka", "tyč",
		"úloha", "blecha"]
	sloveso = ["Najděte", "Spočítejte", "Zapište", "Změřte", "Odhadněte"]
	koho = ["délku", "počet", "množství", "dílky"]
	ceho = ["všech", "správných", "konstatních", "zelených"]
	jmeno = ["řešení", "tahů", "čísel", "kalhot", "koulí", "hadů"]
	kde = ["na zemi", "ve vesmíru", "ve vzduchu", "na šňůře", "v letadle"]
	obory = ["M", "F", "I", "O", "B"]
	
	uloha = Uloha.objects.create(
		nazev=": ".join([tema.nazev, 
			"úloha {}.".format(kod)]),
		nadproblem=tema,
		stav=Problem.STAV_ZADANY,
		zamereni=tema.zamereni,
		autor=tema.autor,
		garant=tema.garant,
		kod=str(kod),
		cislo_zadani=cislo,
		cislo_reseni=cislo_se_vzorakem,
		cislo_deadline=cislo_se_vzorakem,
		max_body = rnd.randint(1, 8)
	)
	
	# Samotný obsah následně vzniklého Textu zadání
	obsah = " ".join(
		[rnd.choice(sloveso), 
		rnd.choice(koho), 
		rnd.choice(ceho), 
		rnd.choice(jmeno), 
		rnd.choice(kde)]
		)
	text_zadani = Text.objects.create(
		na_web = obsah,
		do_cisla = obsah,
		)
	zad = TextNode.objects.create(text = text_zadani, root=tema.temavcislenode_set.first().root)
	uloha_zadani = UlohaZadaniNode.objects.create(uloha=uloha, first_child = zad, root=tema.temavcislenode_set.first().root)
	uloha.ulohazadaninode = uloha_zadani

	# Generování řešení a hodnocení k úloze
	gen_reseni_ulohy(rnd, [cislo], uloha, len(resitele)//4, 1,
					 resitele, resitele)

	return uloha, uloha_zadani


def gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori, resitele):
	logger.info('Generuji úlohy k tématům...')

	# Ke každému ročníku si vezmeme příslušná čísla a témata
	for rocnik, cisla, temata in zip(rocniky, rocnik_cisla, rocnik_temata):
		# Do každého čísla nagenerujeme ke každému témátku pár úložek
		for cislo in cisla:
			print("Generuji úložky do {}-tého čísla".format(cislo.poradi))
			# Vzorák bude o dvě čísla dál
			cislo_se_vzorakem = Cislo.objects.filter(
					rocnik=rocnik,
					poradi=str(int(cislo.poradi) + 2),
					)
			# Pokud není číslo pro vzorák, tak se dá do posledního čísla 
			# (i kdyby tam mělo být zadání i řešení...)
			# Tohle sice umožňuje vygenerovat vzorák do čísla dávno po konci témátka, 
			# ale to nám pro jednoduchost nevadí.
			if len(cislo_se_vzorakem) == 0:
				cislo_se_vzorakem = cisla[-1]
			else:
				cislo_se_vzorakem = cislo_se_vzorakem.first()

			for tema_node in all_children_of_type(cislo.cislonode, TemaVCisleNode):
				tema = tema_node.tema
					
				# Pokud už témátko skončilo, žádné úložky negenerujeme
				# FIXME: Bylo by hezčí, kdyby se čísla předávala jako Cislo a ne 
				# jako int v té trojici (start, konec, tema)
				if not temata[int(tema.kod)-1][1] >= int(cislo_se_vzorakem.poradi):
					continue
					
				# Generujeme 1 až 4 úložky k tomuto témátku do tohoto čísla.
				for kod in range(1, rnd.randint(1, 4)):
					u, uz = gen_ulohy_tematu(rnd, organizatori, resitele, tema, kod,
						cislo, cislo_se_vzorakem)

					insert_last_child(tema_node, uz)
				
					poc_op = rnd.randint(1, 4)
					uvz = gen_vzoroveho_reseni_ulohy(rnd, organizatori, 
						u, poc_op) 
					
					# Najdeme správný TemaVCisleNode pro vložení vzoráku
					res_tema_node = None;
					for node in all_children(cislo_se_vzorakem.cislonode):
						if isinstance(node, TemaVCisleNode): 
							if node.tema == tema:
								res_tema_node = node
					if res_tema_node is None:
						raise LookupError("Nenalezen Node pro vložení vzoráku")
					insert_last_child(res_tema_node, uvz)
					u.save()
	return

def gen_novinky(rnd, organizatori):
	logger.info('Generuji novinky...')


	jake = ["zábavné", "veselé", "dobrodružné", "skvělé"]
	co = ["soustředění", "Fyziklání", "víkendové setkání"]
	kde = ["na Šumavě", "v Praze", "u Plzně", "na Marsu"]
	kdy = ["Zítra bude", "10. 10. 2020 bude", "V prosinci bude", "V létě bude"]

	for i in range(5):
		text_novinky = " ".join([rnd.choice(kdy), rnd.choice(kde), rnd.choice(jake),
			rnd.choice(co)])
		novinka = Novinky.objects.create(id=i,autor=rnd.choice(organizatori),
			text=(text_novinky+", těšíme se na vás!"),zverejneno=rnd.choice([True,False]))
		novinka.save()
	return

def otec_syn(otec, syn):
	bratr = otec.first_child
	syn.succ = bratr
	otec.first_child = syn
	syn.save()
	otec.save()

def gen_clanek(rnd, organizatori, resitele):
	logger.info("Generuji článek do čísla 22.2")
	clanek = m.Clanek.objects.create(
		nazev="Článek o Lorem ipsum",
		nadproblem=None,
		stav='vyreseny',
		zamereni=['I'],
		garant=rnd.choice(organizatori),
		kod='cl',
		)
	clanek.save()

	reseni = m.Reseni.objects.create(
		zverejneno=True,
		)
	reseni.resitele.add(rnd.choice(resitele))
	reseni.save()

	cislo = m.Cislo.objects.get(rocnik__rocnik=22, poradi=2)
	cislonode = cislo.cislonode

	hodnoceni = m.Hodnoceni.objects.create(
		body=15.0,
		cislo_body=cislo,
		reseni=reseni,
		problem=clanek,
		)
	hodnoceni.save()

	reseninode = m.ReseniNode.objects.create(
		reseni=reseni
		)
	reseninode.save()

	# Bude to celý text
	reseni.text_cely = reseninode
	reseni.save()

	from treenode.treelib import insert_last_child, create_child
	insert_last_child(cislonode, reseninode)

	# Vyrobíme nějaký obsah
	# FIXME: Ten, kdo vymyslel TreeLib (mj. týž, kdo psal tenhle kód),
	# nevyrobil vhodnou funkci, takže to postavíme pozpátku pomocí create_child
	# (které vyrábí _prvního_ syna)
	create_child(reseninode, m.CastNode, nadpis="Lorem ipsum")
	# Taky ten člověk nevyrobil vracení nových věcí...
	castnode = reseninode.first_child
	
	# Úvodní odstaveček
	obsah = "Tohle je zamyšlení o textu lorem ipsum. Začneme a skončíme ukázkou."
	text = m.Text.objects.create(
		na_web=obsah,
		do_cisla=obsah,
		)
	text.save()
	create_child(reseninode, m.TextNode, text=text)

	# Několik odstavců lorem ipsum
	for _ in range(rnd.randint(3, 7)):
		lipsum = lorem.paragraph()
		text = m.Text.objects.create(
			na_web=lipsum,
			do_cisla=lipsum,
			)
		text.save()
		create_child(castnode, m.TextNode, text=text)
	logger.info(f"Článek vygenerován (reseni={reseni.id}, treenode={reseninode.id})")



@transaction.atomic
def create_test_data(size = 6, rnd = None):
	logger.info('Vyrábím testovací data (size={})...'.format(size))

	assert size >= 1
	# pevna pseudo-nahodnost
	rnd = rnd or random.Random(x=42)

	# static URL stranky
	# FIXME: nakopirovat sem vsechny z produkcni databaze
	s = Site.objects.filter(name="example.com")
	f = FlatPage.objects.create(url="/", title="Seminář M&M",
		content = "<p>V&iacute;tejte na str&aacute;nce semin&aacute;ře MaM!</p>")
	print(s)
	f.sites.add(s[0])
	f.save()

	# users
	admin = User.objects.create_superuser(username='admin', email='', password='admin')
	os_admin = Osoba.objects.create(
		user=admin, jmeno='admin', prijmeni='admin',
		prezdivka='admin', pohlavi_muz=1, email='admin@admin.admin',
		telefon='123 456 789', datum_narozeni=datetime.date(2000, 1, 1),
		ulice='admin', mesto='admin', psc='100 00',
		datum_registrace=datetime.date(2020, 9, 6)
	)
	or_admin = Organizator.objects.create(
		osoba=os_admin, organizuje_od=None, organizuje_do=None,
		strucny_popis_organizatora="Organizátor k uživateli Admin"
	)

	usernames = ['anet', 'bara', 'cyril', 'david', 'eva', 'filip']
	users = []
	for usr in usernames[:size]:
		u = User.objects.create_user(username=usr, password=usr)
		u.first_name = usr.capitalize()
		u.save()
		users.append(u)
	print(users)

	# skoly
	skoly = gen_skoly()

	# osoby
	osoby = gen_osoby(rnd, size)

	# resitele a organizatori
	last_rocnik = 25
	organizatori = gen_organizatori(rnd, osoby, last_rocnik)
	resitele = gen_resitele(rnd, osoby, skoly)

	#generování novinek
	novinky = gen_novinky(rnd, organizatori)

	# prijemci
	prijemci = gen_prijemci(rnd, osoby)

	global zlinska
	zlinska.kontaktni_osoba=rnd.choice(osoby)
	zlinska.save()

	# rocniky
	rocniky = gen_rocniky(last_rocnik, size)

	# cisla
	# rocnik_cisla je pole polí čísel (typ Cislo), vnitřní pole odpovídají jednotlivým ročníkům.
	rocnik_cisla = gen_cisla(rnd, rocniky)

	# generování obyčejných úloh do čísel
	gen_ulohy_do_cisla(rnd, organizatori, resitele, rocnik_cisla, rocniky, size)

	# generování témat, zatím v prvních třech číslech po jednom
	# FIXME: více témat
	# rocnik_temata je pole polí trojic (první číslo :int, poslední číslo :int, téma:Tema), přičemž každé vnitřní pole odpovídá ročníku a FIXME: je to takhle fuj a když to někdo vidí poprvé, tak je z toho smutný, protože vůbec neví, co se děje a co má čekat.
	rocnik_temata = gen_temata(rnd, rocniky, rocnik_cisla, organizatori)

	rocnik = Rocnik.objects.filter(rocnik = 23).first()
	dlouhe_tema = gen_dlouhe_tema(rnd, organizatori, rocnik, "Strašně dlouhé téma",
		"MFI", 8)

	# generování úloh k tématům ve všech číslech
	gen_ulohy_k_tematum(rnd, rocniky, rocnik_cisla, rocnik_temata, organizatori, resitele)

	#generování soustředění
	soustredeni = gen_soustredeni(rnd, resitele, organizatori)

	#generování konfer
	konfery = gen_konfery(size, rnd, organizatori, resitele, soustredeni)

	# vytvoreni pdf ke korekturam
	create_test_pdf(rnd, organizatori)

			# TODO: nastavi správně, kolik se čeho generuje, aby rozsahy přibližně odpovídaly
			# FIXME: misto typu ruzne typy objektu a vnoreni do sebe (Tom nechápe, co je tímto fixme míněno)
			# TODO: vytvorit temata s ruznymi vlakny
			# TODO: nagenerovat starsim rocnikum pohadku
			# TODO: nagenerovat články
			# TODO: vecpat obrázky všude, kde to jde
			# TODO: mezičíslo node
			# TODO: přidat ke konferám řešení a dát je do čísel

	# Dohackované vytvoření jednoho článku
	gen_clanek(rnd, organizatori, resitele)

			# TODO: přidat články včetně zařazení do struktury treenodů,
			#	a následně otestovat konsistency check databáze z utils.py
			# 	pomocí stránky /stav

	# obecné nastavení semináře, musí být už přidané ročníky a čísla, jinak se nastaví divně
	nastaveni = Nastaveni.objects.create(
			aktualni_cislo = Cislo.objects.all()[1])