from django.db import models
from django.core.urlresolvers import reverse
from django.db.models.signals import post_save

#from proves.models import Prova

import numpy as np

# Create your models here.

class AssignaturaManager(models.Manager):
	
	def filter_by_instance(self, instance):
		obj_id = instance.id
		qs = super(AssignaturaManager, self).filter(id= obj_id)
		return qs

class Assignatura(models.Model):

	nom 		= models.CharField(max_length=120)
	bio 		= models.TextField(blank=True, null=True)
	curs		= models.ForeignKey('cursos.Curs', related_name='curs_assignatures', blank=True, null=True)
	objects		= AssignaturaManager()

	def get_absolute_url(self):
		return reverse("assignatures-api:detail", kwargs={"pk": self.id})

	def __unicode__(self):
		return "%s - %s" % (self.nom, self.curs)

	# def __unicode__(self):
	# 	return "%s - %s" % (self.nom, self.curs)


class Avaluacio(models.Model):

	nom 		= models.CharField(max_length=120)
	assignatura = models.ForeignKey('Assignatura', related_name='assignatura_avaluacions', blank=True, null=True)

	def get_absolute_url(self):
		return reverse("assignatures-api:avaluacio-detail", kwargs={"pk": self.id})

	def __unicode__(self):
		return "%s %s - Avaluacio %s" % (self.assignatura.nom, self.assignatura.curs.nom, self.nom)


	def get_alumnes(self):
		assignatura = Assignatura.objects.filter(id = self.assignatura.id).all()
		alumnes = assignatura.first().alumne_assignatures.all()
		return alumnes

	def recalculate_proves_avaluacio(self):
		'''
		This method recalculates the final notes of the avaluacio.
		An Avaluacio instance is passed in and:
			1 - alumnes from assignatura associated to that avaluacio are retreived
			2 - all proves from avaluacio are retrieved
			3 - a dictionary is generated with the final nota for each alumne
			4 - along with that dictionary, the avaluacio (Total avaluacio) instance 
				and the queryset of alumnes is returned 
		'''
		qs = self

		# There are two types of proves
		# 	- normal proves (we want to use their notes to calculate the mean)
		#	- autogenerated prova (Avaluacio total) for each avaluacio, where the final notes are kept
		assignatura = Assignatura.objects.filter(id = qs.assignatura.id).all()
		qs_alumnes = assignatura.first().alumne_assignatures.all()

		# since the prova_total is autogenerated with avaluacio, it will be the first in case
		# there are more than one prova with nom field equal to "Total"
		qs_proves = qs.proves_avaluacio.all().exclude(nom__iexact="Total avaluacio")
		# print(qs_proves)
		prova_avaluacio_obj = qs.proves_avaluacio.filter(nom__iexact="Total avaluacio").first()
		# print(prova_avaluacio_obj)
				
		# sum the total weight of all proves in order to update the weight of the prova_avaluacio
		pes_total = 0
		for prova in qs_proves:
			pes_total += prova.pes_total

		# create a list of objects that represents notes_avaluacio
		notes_avaluacio = []
		for alumne in qs_alumnes:
			nota_avaluacio_alumne = []
			for prova in qs_proves:
				# print(prova.notes_prova.all())
				for nota in prova.notes_prova.all():
					if nota.alumne.id == alumne.id:
						nota_avaluacio_alumne.append(nota.nota*prova.pes_total/prova.nota_total)
			notes_avaluacio.append(
				{ 
					"nota": np.sum(nota_avaluacio_alumne)*10/pes_total,
					"prova": prova_avaluacio_obj.id,
					"alumne": alumne.id
				}
			)


		return pes_total, notes_avaluacio, prova_avaluacio_obj, qs_alumnes


	def recalculate_dimensions_avaluacio(self):
		'''
		This method recalculates the final notes of the avaluacio.
		An Avaluacio instance is passed in and:
			1 - alumnes from assignatura associated to that avaluacio are retreived
			2 - all proves from avaluacio are retrieved
			3 - a dictionary is generated with the final nota for each alumne
			4 - along with that dictionary, the avaluacio (Total avaluacio) instance 
				and the queryset of alumnes is returned 
		'''
		qs = self

		# There are two types of proves
		# 	- normal proves (we want to use their notes to calculate the mean)
		#	- autogenerated dimensio (Avaluacio total) for each avaluacio, where the final notes are kept
		assignatura = Assignatura.objects.filter(id = qs.assignatura.id).all()
		qs_alumnes = assignatura.first().alumne_assignatures.all()

		# since the prova_total is autogenerated with avaluacio, it will be the first in case
		# there are more than one dimensio with nom field equal to "Total"
		qs_dimensions = qs.dimensions_avaluacio.all().exclude(nom__iexact="Total avaluacio")
		
		# print(qs_dimensions)
		dimensio_avaluacio_obj = qs.dimensions_avaluacio.filter(nom__iexact="Total avaluacio").first()
				
		# sum the total weight of all proves in order to update the weight of the prova_avaluacio
		pes_total = 0
		for dimensio in qs_dimensions:
			pes_total += dimensio.pes_total

		# create a list of objects that represents notes_avaluacio
		notes_avaluacio = []
		for alumne in qs_alumnes:
			nota_avaluacio_alumne = []
			for dimensio in qs_dimensions:
				# print(prova.notes_dimensio.all())
				for nota in dimensio.notes_dimensio.all():
					if nota.alumne.id == alumne.id:
						nota_avaluacio_alumne.append(nota.nota*dimensio.pes_total/dimensio.nota_total)
			notes_avaluacio.append(
				{ 
					"nota": np.sum(nota_avaluacio_alumne)*10/pes_total,
					"dimensio": dimensio_avaluacio_obj.id,
					"alumne": alumne.id
				}
			)


		return pes_total, notes_avaluacio, dimensio_avaluacio_obj, qs_alumnes