# -*- coding: utf-8 -*-
import logging

from django.db import models
from django.urls import reverse
from django.contrib.contenttypes.models import ContentType

from unidecode import unidecode # Používám pro získání ID odkazu (ještě je to někde po někom zakomentované)

from polymorphic.models import PolymorphicModel

from . import personalni as pm

from .pomocne import Text

logger = logging.getLogger(__name__)

from seminar.models import tvorba as am

class TreeNode(PolymorphicModel):
	class Meta:
		db_table = "seminar_nodes_treenode"
		verbose_name = "TreeNode"
		verbose_name_plural = "TreeNody"

	# TODO: Nechceme radši jako root vyžadovat přímo RocnikNode?
	root = models.ForeignKey('TreeNode',
		related_name="potomci_set",
		null = True,
		blank = False,
		on_delete = models.SET_NULL, # Vrcholy s null kořenem jsou sirotci bez ročníku 
		verbose_name="kořen stromu")
	first_child = models.OneToOneField('TreeNode',
		related_name='father_of_first',
		null = True,
		blank = True,
		on_delete=models.SET_NULL,
		verbose_name="první potomek")
	succ = models.OneToOneField('TreeNode',
		related_name="prev",
		null = True,
		blank = True,
		on_delete=models.SET_NULL,
		verbose_name="další element na stejné úrovni")
	nazev = models.TextField("název tohoto node",
		help_text = "Tento název se zobrazuje v nabídkách pro výběr vhodného TreeNode",
		blank=False, 
		null=True) # Nezveřejnitelný název na stránky - pouze do adminu
	zajimave = models.BooleanField(default = False,
		verbose_name = "Zajímavé",
		help_text = "Zobrazí se daná věc na rozcestníku témátek")
	srolovatelne = models.BooleanField(null = True, blank = True,
		verbose_name = "Srolovatelné",
		help_text = "Bude na stránce témátka možnost tuto položku skrýt")

	def getOdkazStr(self): # String na rozcestník
		return self.first_child.getOdkazStr()

	def getOdkaz(self): # ID HTML tagu, na který se bude scrollovat #{{self.getOdkaz}}
	# Jsem si vědom, že tu potenciálně vznikají kolize.
	# Přijdou mi natolik nepravděpodobné, že je neřeším
	# Chtěl jsem ale hezké odkazy
		string = unidecode(self.getOdkazStr())
		returnVal = ""
		i = 0	
		while len(returnVal) < 16: # Max 15 znaků
			if i == len(string):
				break
			if string[i] == " ":
				returnVal += "-"
			if string[i].isalnum():
				returnVal += string[i].lower()
			i += 1
		return returnVal

	def __str__(self):
		if self.nazev:
			return self.nazev
		else:
			#TODO: logování
			return "Nepojmenovaný Treenode"
	
	def save(self, *args, **kwargs):
		self.aktualizuj_nazev()
		super().save(*args, **kwargs)

	def aktualizuj_nazev(self):
		raise NotImplementedError("Pokus o aktualizaci názvu obecného TreeNode místo konkrétní instance")

	def get_admin_url(self):
		content_type = ContentType.objects.get_for_model(self.__class__)
		return reverse("admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,))

class RocnikNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_rocnik'
		verbose_name = 'Ročník (Node)'
		verbose_name_plural = 'Ročníky (Node)'
	rocnik = models.OneToOneField(am.Rocnik,
		on_delete = models.PROTECT, # Pokud chci mazat ročník, musím si Node pořešit ručně
		verbose_name = "ročník")

	def aktualizuj_nazev(self):
		self.nazev = "RocnikNode: "+str(self.rocnik)

class CisloNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_cislo'
		verbose_name = 'Číslo (Node)'
		verbose_name_plural = 'Čísla (Node)'
	cislo = models.OneToOneField(am.Cislo,
		on_delete = models.PROTECT, # Pokud chci mazat číslo, musím si Node pořešit ručně
		verbose_name = "číslo")

	def aktualizuj_nazev(self):
		self.nazev = "CisloNode: "+str(self.cislo)

	def getOdkazStr(self):
		return "Číslo " + str(self.cislo)

class MezicisloNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_mezicislo'
		verbose_name = 'Mezičíslo (Node)'
		verbose_name_plural = 'Mezičísla (Node)'

	# TODO: Využít TreeLib
	def aktualizuj_nazev(self):
		from treenode.treelib import safe_pred
		if safe_pred(self) is not None:
			if (self.prev.get_real_instance_class() != CisloNode and
				self.prev.get_real_instance_class() != MezicisloNode):
					raise ValueError("Předchůdce není číslo!")
			posledni = self.prev.cislo
			self.nazev = "MezicisloNode: Mezičíslo po čísle"+str(posledni)
		elif self.root:
			if self.root.get_real_instance_class() != RocnikNode:
				raise ValueError("Kořen stromu není ročník!")
			rocnik = self.root.rocnik
			self.nazev = "MezicisloNode: První mezičíslo ročníku "+str(rocnik)
		else:
			print("!!!!! Nějaké neidentifikované mezičíslo !!!!!")
			self.nazev = "MezicisloNode: Neidentifikovatelné mezičíslo!"
	def getOdkazStr(self):
		return "Obsah dostupný pouze na webu"

class TemaVCisleNode(TreeNode):
	""" Obsahuje příspěvky k tématu v daném čísle """
	class Meta:
		db_table = 'seminar_nodes_temavcisle'
		verbose_name = 'Téma v čísle (Node)'
		verbose_name_plural = 'Témata v čísle (Node)'
	tema = models.ForeignKey(am.Tema,
		on_delete=models.PROTECT, # Pokud chci mazat téma, musím si Node pořešit ručně
		verbose_name = "téma v čísle")

	def aktualizuj_nazev(self):
		self.nazev = "TemaVCisleNode: "+str(self.tema)

	def getOdkazStr(self):
		return str(self.tema)

class OrgTextNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_orgtextnode'
		verbose_name = 'Organizátorský článek (Node)'
		verbose_name_plural = 'Organizátorské články (Node)'
	
	organizator = models.ForeignKey(pm.Organizator,
		null=False,
		blank=False,
		on_delete=models.DO_NOTHING,
		verbose_name="Organizátor",
		)
	org_verejny = models.BooleanField(default = True,
		verbose_name = "Org je veřejný?",
		help_text = "Pokud ano, bude org pod článkem podepsaný",
		null=False,
		)

	def aktualizuj_nazev(self):
		return f"OrgTextNode začínající následujícim: {self.first_child.nazev}"

	# FIXME!!!
	#def getOdkazStr(self):
	#	return str(self.clanek)


class UlohaZadaniNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_uloha_zadani'
		verbose_name = 'Zadání úlohy (Node)'
		verbose_name_plural = 'Zadání úloh (Node)'
	uloha = models.OneToOneField(am.Uloha,
		on_delete=models.PROTECT, # Pokud chci mazat téma, musím si Node pořešit ručně
		verbose_name = "úloha",
		null=True,
		blank=False)

	def aktualizuj_nazev(self):
		self.nazev = "UlohaZadaniNode: "+str(self.uloha)

	def getOdkazStr(self):
		return str(self.uloha)


class PohadkaNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_pohadka'
		verbose_name = 'Pohádka (Node)'
		verbose_name_plural = 'Pohádky (Node)'
	pohadka = models.OneToOneField(am.Pohadka,
		on_delete=models.PROTECT, # Pokud chci mazat pohádku, musím si Node pořešit ručně
		verbose_name = "pohádka",
		)

	def aktualizuj_nazev(self):
		self.nazev = "PohadkaNode: "+str(self.pohadka)

class UlohaVzorakNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_uloha_vzorak'
		verbose_name = 'Vzorák úlohy (Node)'
		verbose_name_plural = 'Vzoráky úloh (Node)'
	uloha = models.OneToOneField(am.Uloha,
		on_delete=models.PROTECT, # Pokud chci mazat téma, musím si Node pořešit ručně
		verbose_name = "úloha",
		null=True,
		blank=False)

	def aktualizuj_nazev(self):
		self.nazev = "UlohaVzorakNode: "+str(self.uloha)

	def getOdkazStr(self):
		return str(self.uloha)


class TextNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_obsah'
		verbose_name = 'Text (Node)'
		verbose_name_plural = 'Text (Node)'
	text = models.ForeignKey(Text,
		on_delete=models.CASCADE,
		verbose_name = 'text')
	
	def aktualizuj_nazev(self):
		self.nazev = "TextNode: "+str(self.text)

	def getOdkazStr(self):
		return str(self.text)


class CastNode(TreeNode):
	class Meta:
		db_table = 'seminar_nodes_cast'
		verbose_name = 'Část (Node)'
		verbose_name_plural = 'Části (Node)'
	
	nadpis = models.CharField('Nadpis', max_length=100, help_text = 'Nadpis podvěšené části obsahu')

	def aktualizuj_nazev(self):
		self.nazev = "CastNode: "+str(self.nadpis)

	def getOdkazStr(self):
		return str(self.nadpis)