from rest_framework import serializers
from rest_polymorphic.serializers import PolymorphicSerializer

from odevzdavatko.models import Reseni
from tvorba.models import Problem, Uloha

from .models import RocnikNode, CisloNode, MezicisloNode, TemaVCisleNode, OrgTextNode, PohadkaNode, TextNode, TreeNode, CastNode, UlohaZadaniNode, UlohaVzorakNode, ReseniNode
from .models import Text
from treenode import treelib

DEFAULT_NODE_DEPTH = 2


class TextSerializer(serializers.ModelSerializer):
	class Meta:
		model = Text
		fields = '__all__'

class ProblemSerializer(serializers.ModelSerializer):
	class Meta:
		model = Problem
		fields = '__all__'

class UlohaSerializer(serializers.ModelSerializer):
	class Meta:
		model = Uloha
		fields = '__all__'

class ReseniSerializer(serializers.ModelSerializer):
	class Meta:
		model = Reseni
		fields = '__all__'
	
class RocnikNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = RocnikNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class CisloNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = CisloNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class MezicisloNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = MezicisloNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class TemaVCisleNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = TemaVCisleNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class OrgTextNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = OrgTextNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class PohadkaNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = PohadkaNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class TextNodeSerializer(serializers.ModelSerializer):
	text = TextSerializer()

	class Meta:
		model = TextNode
		fields = ('id','text','polymorphic_ctype')
		depth = DEFAULT_NODE_DEPTH

class TextNodeWriteSerializer(serializers.ModelSerializer):
	text = TextSerializer()

	def update(self,node,validated_data):
		node.text.na_web = validated_data.get('text').get('na_web')
		node.text.save()
		return node

	class Meta:
		model = TextNode
		fields = ('id','text')
		depth = DEFAULT_NODE_DEPTH

class TextNodeCreateSerializer(serializers.ModelSerializer):
	text = TextSerializer()
	refnode = serializers.CharField()
	where = serializers.CharField()

	def create(self,validated_data):
		temp_text = validated_data.pop('text')
		where = validated_data.pop('where')
		refnode_id = validated_data.pop('refnode')
		refnode = TreeNode.objects.get(pk=refnode_id)
		text = Text.objects.create(**temp_text)
		if where == 'syn':
			node = treelib.create_child(refnode,TextNode,text=text)
		elif where == 'za':
			node = treelib.create_node_after(refnode,TextNode,text=text)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,TextNode,text=text)
		node.where = None
		node.refnode = None
		return node

	class Meta:
		model = TextNode
		fields = ('text','where','refnode')
		depth = DEFAULT_NODE_DEPTH

class CastNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = CastNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class CastNodeCreateSerializer(serializers.ModelSerializer):
	refnode = serializers.CharField()
	where = serializers.CharField()

	def create(self,validated_data):
		temp_nadpis = validated_data.pop('nadpis')
		where = validated_data.pop('where')
		refnode_id = validated_data.pop('refnode')
		refnode = TreeNode.objects.get(pk=refnode_id)
		if where == 'syn':
			node = treelib.create_child(refnode,CastNode,nadpis=temp_nadpis)
		elif where == 'za':
			node = treelib.create_node_after(refnode,CastNode,nadpis=temp_nadpis)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,CastNode,nadpis=temp_nadpis)
		node.where = None
		node.refnode = None
		return node

	class Meta:
		model = CastNode
		fields = ('nadpis','where','refnode')
		depth = DEFAULT_NODE_DEPTH

class UlohaZadaniNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = UlohaZadaniNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class UlohaZadaniNodeWriteSerializer(serializers.ModelSerializer):
	uloha = UlohaSerializer()

	def update(self,node,validated_data):
		node.uloha.max_body = validated_data.get('uloha').get('max_body')
		node.uloha.kod = validated_data.get('uloha').get('kod')
		node.uloha.nazev = validated_data.get('uloha').get('nazev')
		node.uloha.save()
		return node

	class Meta:
		model = TextNode
		fields = ('id','uloha')
		depth = DEFAULT_NODE_DEPTH

class UlohaZadaniNodeCreateSerializer(serializers.ModelSerializer):
	uloha = UlohaSerializer()
	refnode = serializers.IntegerField()
	where = serializers.CharField()

	def create(self,validated_data):
		# text_zadani = validated_data.pop('text_zadani')
		temp_uloha = validated_data.pop('uloha')
		where = validated_data.pop('where')
		refnode_id = validated_data.pop('refnode')
		refnode = TreeNode.objects.get(pk=refnode_id)

		# Z cesty ke koreni stromu zjistime, v jakem jsme tematu a v jakem cisle
		cislo = None
		tema = None
		travelnode = refnode
		while travelnode is not None:
			if isinstance(travelnode, TemaVCisleNode):
				tema = travelnode.tema
			if isinstance(travelnode, CisloNode):
				cislo = travelnode.cislo
			travelnode = treelib.get_parent(travelnode)
		# Vyrobime ulohu
		uloha = Uloha.objects.create(cislo_zadani=cislo, nadproblem = tema, **temp_uloha)
		
		# A vyrobime UlohaZadaniNode
		if where == 'syn':
			node = treelib.create_child(refnode,UlohaZadaniNode,uloha = uloha)
		elif where == 'za':
			node = treelib.create_node_after(refnode,UlohaZadaniNode,uloha = uloha)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,UlohaZadaniNode,uloha = uloha)
		node.where = None
		node.refnode = None
		node.max_body = None
		node.kod = None
		return node

	class Meta:
		model = UlohaZadaniNode
		fields = ('uloha','where','refnode')
		depth = DEFAULT_NODE_DEPTH

class UlohaVzorakNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = UlohaVzorakNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH
	
class UlohaVzorakNodeWriteSerializer(serializers.ModelSerializer):
	uloha = serializers.PrimaryKeyRelatedField(queryset=Uloha.objects.all(), many=False, read_only=False)

	class Meta:
		model = UlohaVzorakNode
		fields = ('id','uloha')
		depth = DEFAULT_NODE_DEPTH
	

class UlohaVzorakNodeCreateSerializer(serializers.ModelSerializer):
	uloha_id = serializers.IntegerField()
	refnode = serializers.IntegerField()
	where = serializers.CharField()

	def create(self, validated_data):
		uloha_id = validated_data.pop('uloha_id')
		uloha = Uloha.objects.get(pk=uloha_id)
		where = validated_data.pop('where')
		refnode_id = validated_data.pop('refnode')
		refnode = TreeNode.objects.get(pk=refnode_id)

		if where == 'syn':
			node = treelib.create_child(refnode,UlohaVzorakNode,uloha = uloha)
		elif where == 'za':
			node = treelib.create_node_after(refnode,UlohaVzorakNode,uloha = uloha)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,UlohaVzorakNode,uloha = uloha)
		node.refnode = None
		node.where = None
		node.uloha_id = None
		
		return node

	class Meta:
		model = UlohaVzorakNode
		fields = ('refnode', 'uloha_id', 'where')
		depth = DEFAULT_NODE_DEPTH




class ReseniNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = ReseniNode
		fields = '__all__'
		depth = DEFAULT_NODE_DEPTH

class ReseniNodeWriteSerializer(serializers.ModelSerializer):
	reseni = serializers.PrimaryKeyRelatedField(queryset=Reseni.objects.all(), many=False, read_only=False)

	class Meta:
		model = ReseniNode
		fields = ('id','reseni')
		depth = DEFAULT_NODE_DEPTH

class ReseniNodeCreateSerializer(serializers.ModelSerializer):
	reseni_id = serializers.IntegerField()
	refnode = serializers.IntegerField()
	where = serializers.CharField()

	def create(self,validated_data):
		# text_zadani = validated_data.pop('text_zadani')
		reseni_id = validated_data.pop('reseni_id')
		reseni = Reseni.objects.get(pk=reseni_id)
		where = validated_data.pop('where')
		refnode_id = validated_data.pop('refnode')
		refnode = TreeNode.objects.get(pk=refnode_id)
		
		# A vyrobime UlohaZadaniNode
		if where == 'syn':
			node = treelib.create_child(refnode,ReseniNode,reseni = reseni)
		elif where == 'za':
			node = treelib.create_node_after(refnode,ReseniNode,reseni = reseni)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,ReseniNode,reseni = reseni)
		node.where = None
		node.refnode = None
		node.reseni_id = None
		return node

	class Meta:
		model = ReseniNode
		fields = ('reseni_id','where','refnode')
		depth = DEFAULT_NODE_DEPTH


class TreeNodeSerializer(PolymorphicSerializer):
	model_serializer_mapping = {
		RocnikNode: RocnikNodeSerializer,
		CisloNode: CisloNodeSerializer,
		MezicisloNode: MezicisloNodeSerializer,
		TemaVCisleNode: TemaVCisleNodeSerializer,
		OrgTextNode: OrgTextNodeSerializer,
		UlohaZadaniNode: UlohaZadaniNodeSerializer,
		UlohaVzorakNode: UlohaVzorakNodeSerializer,
		PohadkaNode: PohadkaNodeSerializer,
		TextNode: TextNodeSerializer,
		CastNode: CastNodeSerializer,
		ReseniNode: ReseniNodeSerializer,
	}