from rest_framework import serializers
from rest_polymorphic.serializers import PolymorphicSerializer

import seminar.models as m
from seminar import treelib

DEFAULT_NODE_DEPTH = 2


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

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

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

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

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

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

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

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

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

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

	class Meta:
		model = m.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 = m.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 = m.TreeNode.objects.get(pk=refnode_id)
		text = m.Text.objects.create(**temp_text)
		if where == 'syn':
			node = treelib.create_child(refnode,m.TextNode,text=text)
		elif where == 'za':
			node = treelib.create_node_after(refnode,m.TextNode,text=text)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,m.TextNode,text=text)
		node.where = None
		node.refnode = None
		return node

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

class CastNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = m.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 = m.TreeNode.objects.get(pk=refnode_id)
		if where == 'syn':
			node = treelib.create_child(refnode,m.CastNode,nadpis=temp_nadpis)
		elif where == 'za':
			node = treelib.create_node_after(refnode,m.CastNode,nadpis=temp_nadpis)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,m.CastNode,nadpis=temp_nadpis)
		node.where = None
		node.refnode = None
		return node

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

class UlohaZadaniNodeSerializer(serializers.ModelSerializer):
	class Meta:
		model = m.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 = m.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 = m.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, m.TemaVCisleNode):
				tema = travelnode.tema
			if isinstance(travelnode, m.CisloNode):
				cislo = travelnode.cislo
			travelnode = treelib.get_parent(travelnode)
		# Vyrobime ulohu
		uloha = m.Uloha.objects.create(cislo_zadani=cislo, nadproblem = tema, **temp_uloha)
		
		# A vyrobime UlohaZadaniNode
		if where == 'syn':
			node = treelib.create_child(refnode,m.UlohaZadaniNode,uloha = uloha)
		elif where == 'za':
			node = treelib.create_node_after(refnode,m.UlohaZadaniNode,uloha = uloha)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,m.UlohaZadaniNode,uloha = uloha)
		node.where = None
		node.refnode = None
		node.max_body = None
		node.kod = None
		return node

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

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

	class Meta:
		model = m.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 = m.Uloha.objects.get(pk=uloha_id)
		where = validated_data.pop('where')
		refnode_id = validated_data.pop('refnode')
		refnode = m.TreeNode.objects.get(pk=refnode_id)

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

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




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

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

	class Meta:
		model = m.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 = m.Reseni.objects.get(pk=reseni_id)
		where = validated_data.pop('where')
		refnode_id = validated_data.pop('refnode')
		refnode = m.TreeNode.objects.get(pk=refnode_id)
		
		# A vyrobime UlohaZadaniNode
		if where == 'syn':
			node = treelib.create_child(refnode,m.ReseniNode,reseni = reseni)
		elif where == 'za':
			node = treelib.create_node_after(refnode,m.ReseniNode,reseni = reseni)
		elif where == 'pred':
			node = treelib.create_node_before(refnode,m.ReseniNode,reseni = reseni)
		node.where = None
		node.refnode = None
		node.reseni_id = None
		return node

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


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