# -*- coding: utf-8 -*-
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.db.models import Q

# Create your models here.

class Comment(models.Model):
	lang = models.CharField(max_length=5)	
	comment = models.CharField(max_length=100)	
	level = models.CharField(max_length=5)

class Log(models.Model):
	game = models.CharField(max_length=30)
	date = models.DateField(blank=True, null=True)
	userinput = models.CharField(max_length=200)
	iscorrect = models.BooleanField()
	correct = models.CharField(max_length=200)
	example = models.CharField(max_length=200,null=True)
	feedback = models.CharField(max_length=200,null=True)
	comment = models.CharField(max_length=200)

class Semtype(models.Model):
	semtype = models.CharField(max_length=50)
	
	def __unicode__(self):
		return self.semtype

class Source(models.Model):
	type = models.CharField(max_length=20)
	name = models.CharField(max_length=20)
	
	
	def __unicode__(self):
		if self.type and self.name:
			return "%s: %s" % (self.type, self.name)
		elif self.name:
			return "%s" % self.name

# First, define the Manager subclass.
class NPosManager(models.Manager):
	def get_query_set(self):
		return super(NPosManager, self).get_query_set().filter(pos='N')

class Dialect(models.Model):
	dialect = models.CharField(max_length=5)
	name = models.CharField(max_length=100)

def Translations2(target_lang):
	if target_lang in ["nob", "swe", "sme", "eng", "deu", "sma", "no"]:
		if target_lang == "nob" or "no":	related = 'translations2nob'
		if target_lang == "swe":	related = 'translations2swe'
		if target_lang == "sme":	related = 'translations2sme'
		if target_lang == "eng":	related = 'translations2eng'
		if target_lang == "deu":	related = 'translations2deu'
		if target_lang == "sma":	related = 'translations'
		return related
	else:
		return None


# class Nob(models.Manager):
# 	def get_query_set(self):
# 		return super(Nob, self).get_query_set().filter(language='nob')

class MorphPhonTag(models.Model):
	stem		 = models.CharField(max_length=20)
	wordclass	= models.CharField(max_length=20)
	diphthong	= models.CharField(max_length=20)
	gradation	= models.CharField(max_length=20)
	rime		 = models.CharField(max_length=20)
	soggi		= models.CharField(max_length=20)
	# diphthong	= models.CharField(max_length=20)
	
	def __unicode__(self):
		attrs = [self.stem, 
				self.wordclass, 
				self.diphthong, 
				self.gradation, 
				self.rime, 
				self.soggi]
		
		S = unicode('/'.join([a for a in attrs if a.strip()])).encode('utf-8')
		return S
	
	class Meta:
		unique_together = ("stem",
							"wordclass",
							"diphthong",
							"gradation",
							"rime",
							"soggi",)

class Word(models.Model):
	"""
		>>> a = Word.objects.create(lemma='omg')
		>>> a.wordnob_set.create(lemma='bbq')	
	"""
	wordid = models.CharField(max_length=200)
	language = models.CharField(max_length=5, default='sma')
	lemma = models.CharField(max_length=200)
	presentationform = models.CharField(max_length=5)
	pos = models.CharField(max_length=5)
	# TODO: increase length of PoS to accommodate 'PHRASE'. Change requires dropping all tables
	# and recreating.
	# TODO: pos = models.CharField(max_length=12)
	stem = models.CharField(max_length=20)
	wordclass = models.CharField(max_length=8)
	valency = models.CharField(max_length=10)
	semtype = models.ManyToManyField(Semtype)
	source = models.ManyToManyField(Source)
	diphthong = models.CharField(max_length=5)
	gradation = models.CharField(max_length=20)
	rime = models.CharField(max_length=20)
	attrsuffix = models.CharField(max_length=20)
	soggi = models.CharField(max_length=10)
	compare = models.CharField(max_length=5)
	# translations2nob = models.ManyToManyField('Wordnob')
	# translations2swe = models.ManyToManyField('Wordswe')
	# translations2sme = models.ManyToManyField('Wordsme')
	# translations2eng = models.ManyToManyField('Wordeng')
	# translations2deu = models.ManyToManyField('Worddeu')
	frequency = models.CharField(max_length=10)
	geography = models.CharField(max_length=10)
	objects = models.Manager() # The default manager.
	N_objects = NPosManager() # The Noun-specific manager
	tcomm = models.BooleanField(default=False)
	# nob = Nob()
	morphophon = models.ForeignKey(MorphPhonTag, null=True)
	
	def morphTag(self, nosave=True):
		if not self.morphophon:
			kwargs = {
				'stem':		 self.stem,
				'wordclass':	self.wordclass,
				'diphthong':	self.diphthong,
				'gradation':	self.gradation,
				'rime':		 self.rime,
				'soggi':		self.soggi,
			}
			morphtag, create = MorphPhonTag.objects.get_or_create(**kwargs)
			if nosave:
				return morphtag
			else:
				self.morphophon = morphtag
				self.save()
			
		
	def __init__(self, *args, **kwargs):
		super(Word, self).__init__(*args, **kwargs)
		self.definition = self.lemma
		if self.stem in ['3syll', 'trisyllabic']:
			self.wordclass = _('Odd')
		
		from functools import partial
		
		self.translations2nob = partial(self.translations2, target_lang='nob')()
		self.translations2eng = partial(self.translations2, target_lang='eng')()
		self.translations2deu = partial(self.translations2, target_lang='deu')()
		self.translations2swe = partial(self.translations2, target_lang='swe')()
		self.translations2sme = partial(self.translations2, target_lang='sme')()
		
	def create(self, *args, **kwargs):
		morphtag = self.morphTag()
		self.morphophon = morphtag
		self.pos = self.pos.lower().capitalize()
		super(Word, self).create(*args, **kwargs)
	
	def save(self, *args, **kwargs):
		""" Words model has an override to uppercase pos attribute on save, 
			in case data isn't saved properly.
			""" 
		morphtag = self.morphTag()
		self.pos = self.pos.lower().capitalize()
		self.morphophon = morphtag
		
		super(Word, self).save(*args, **kwargs)

	def __unicode__(self):
		return self.lemma
	
	def sem_types_admin(self):
		return ', '.join([item.semtype for item in self.semtype.order_by('semtype').all()])
	
	def source_admin(self):
		return ', '.join([item.name for item in self.source.order_by('name').all()])
	
	def translations2(self, target_lang):
		"""
			Returns obj.translations2XXX for string
		"""
		target_lang = target_lang[-3::]
		# related = Translations2(target_lang)
		# return self.__getattribute__(related)
		return self.wordtranslation_set.filter(language__startswith=target_lang)
	
	def baseform(self):
		"""
			Returns the infinitive/recitation Form for the Word.
			
			V - Inf
			N - Nom
			A - Attr
			
			Take a look at code in game.BareGame.get_baseform and move that here.
		"""
		
		pos_base = {
			'V': 'Inf',
			'N': 'Nom',
			'A': 'Attr',
			'Pron': 'Nom',
		}
		
		try:
			return self.form_set.filter(tag__string__icontains=pos_base[self.pos])[0]
		except:
			return None
	
# TODO: Wordxxx need to be one object
# TODO: admin interface is going to have problems loading tons of words, should use search field instead


class WordTranslation(models.Model):
	""" Abstract parent class for all translations.
		Meta.abstract = True
		
		TODO: null=True necessary?
	"""
	word = models.ForeignKey(Word)
	language = models.CharField(max_length=5)
	wordid = models.CharField(max_length=200)
	lemma = models.CharField(max_length=200, blank=True)
	phrase = models.TextField(blank=True)
	explanation = models.TextField(blank=True)
	# TODO: pos = models.CharField(max_length=12)
	pos = models.CharField(max_length=5)
	semtype = models.ManyToManyField(Semtype)
	source = models.ManyToManyField(Source)
	# translations = models.ManyToManyField(Word)
	frequency = models.CharField(max_length=10)
	geography = models.CharField(max_length=10)
	tcomm = models.BooleanField(default=False)
	tcomm_pref = models.BooleanField(default=False)
	# TODO: 
	# Need a method here which returns the correct translation string
	
	# lemma
	# lemma (phrase)
	# lemma (phrase) – explanation
	def _getTrans(self):
		if self.lemma:
			return self.lemma
		elif self.phrase:
			return self.phrase
		elif self.explanation:
			return self.explanation
		else:
			return ''
	
	def _getAnswer(self):
		word_answers = []
		if self.lemma:
			word_answers.append(self.lemma)
		elif self.phrase:
			word_answers.append(self.phrase)
		return word_answers
		
	def __unicode__(self):
		return self._getTrans().encode('utf-8')
	
	def __init__(self, *args, **kwargs):
		super(WordTranslation, self).__init__(*args, **kwargs)
		self.definition = self._getTrans()
		self.word_answers = self._getAnswer()
	
	
	# class Meta:
	# 	abstract = True

# Following are subclassed from above, no need to add anything special.
# 
# class Wordnob(WordTranslation):		
# 	class Meta: abstract = True
# class Wordswe(WordTranslation):		
# 	class Meta: abstract = True
# class Wordsme(WordTranslation):		
# 	class Meta: abstract = True
# class Wordeng(WordTranslation):		
# 	class Meta: abstract = True
# class Worddeu(WordTranslation):		
# 	class Meta: abstract = True

class Tagset(models.Model):
	tagset = models.CharField(max_length=25)
	
	def __unicode__(self):
		return self.tagset

class Tagname(models.Model):
	tagname = models.CharField(max_length=25)
	tagset = models.ForeignKey(Tagset)	
	
	def __unicode__(self):
		return self.tagname

class Tag(models.Model):
	string = models.CharField(max_length=25)
	pos = models.CharField(max_length=5)
	case = models.CharField(max_length=5)
	number = models.CharField(max_length=5)
	possessive = models.CharField(max_length=5)
	grade = models.CharField(max_length=10)
	infinite = models.CharField(max_length=10)
	personnumber = models.CharField(max_length=8)
	conneg = models.CharField(max_length=5)
	polarity = models.CharField(max_length=5)
	tense = models.CharField(max_length=5)
	mood = models.CharField(max_length=5)
	subclass = models.CharField(max_length=10)
	attributive = models.CharField(max_length=5)
	class Admin:
		pass
		
	def __unicode__(self):
		return self.string

class Form(models.Model):
	word = models.ForeignKey(Word)
	tag = models.ForeignKey(Tag)
	fullform = models.CharField(max_length=200)
	
	def __unicode__(self):
		return u'%s' % self.fullform.decode('utf-8')
		# Testing-- related lookups seem to be quite slow in MySQL...?
		# return '%s; %s+%s' % (self.fullform, self.word.lemma, self.tag)
	
	def getBaseform(self, match_num=False):
		""" Gets the base form (e.g., citation/dictionary form) for 
			the wordform. Nouns -> Nom+Sg, Verbs -> Inf

			@param match_num:
				True - If the form supplied is a noun and plural
					   the baseform will be Nominative Plural
		"""

		if self.tag.pos in ['N', 'n', 'Pron']:
			if match_num:
				number = self.tag.number
			else:
				number = 'Sg'
			baseform = self.word.form_set.filter(tag__case='Nom')\
						.filter(tag__number=number)
		elif self.tag.pos in ['V', 'v']:
			baseform = self.word.form_set.filter(tag__infinite='Inf')
		elif self.tag.pos in ['A', 'a']:
			baseform = self.word.form_set.filter(tag__attributive='',
												 	tag__case='Nom',
													tag__number='Sg',
													tag__grade='')
		else:
			raise Form.DoesNotExist

		try:
			return baseform[0]
		except IndexError:
			raise Form.DoesNotExist





############# MORFA FEEDBACK

class Feedbackmsg(models.Model):
	"""
		XML code for messages in messages.xml
	"""
	msgid = models.CharField(max_length=100)
	
	def __unicode__(self):
		return self.msgid


class Feedbacktext(models.Model):
	"""
		Message text in messages.xml
	"""
	message = models.CharField(max_length=200)
	language = models.CharField(max_length=6)
	feedbackmsg = models.ForeignKey(Feedbackmsg)
	
	def __unicode__(self):
		attrs = [
				self.language,
				self.message, 
			]
		S = unicode('/'.join([a for a in attrs if a.strip()])).encode('utf-8')
		return self.language + u':' + self.message

class Feedback(models.Model):
	messages = models.ManyToManyField(Feedbackmsg)
	# TODO: pos = models.CharField(max_length=12)
	# tag = models.ForeignKey(Tag)
	
	# Word morphology / classes
	attrsuffix = models.CharField(max_length=10,null=True,blank=True)
	dialects = models.ManyToManyField(Dialect)
	# diphthong = models.CharField(max_length=5,blank=True,null=True)
	# gradation = models.CharField(max_length=15,null=True,blank=True)
	# rime = models.CharField(max_length=20,null=True,blank=True)
	soggi = models.CharField(max_length=10,null=True,blank=True)
	stem = models.CharField(max_length=20,blank=True,null=True)
	wordclass = models.CharField(max_length=20,blank=True,null=True)

	# Tag / inflection 
	attributive = models.CharField(max_length=10,null=True,blank=True)
	case2 = models.CharField(max_length=5,null=True,blank=True)
	grade = models.CharField(max_length=10,null=True,blank=True)
	mood = models.CharField(max_length=10,null=True,blank=True)
	number = models.CharField(max_length=5,null=True,blank=True)
	personnumber = models.CharField(max_length=5,null=True,blank=True)
	pos = models.CharField(max_length=5,blank=True,null=True)
	tense = models.CharField(max_length=5,null=True,blank=True)

	class Meta:
		# Sma doesn't have "diphthong","gradation"
		# Sma doesn't have "rime"
		# unique_together = ("tag")
		unique_together = ( "pos",
							"stem",
							"soggi",
							"wordclass",
							
							"case2",
							"number",
						
							"personnumber",
							"tense",
							"mood",
						
							"grade",
							"attrsuffix",
							"attributive", )

	def __unicode__(self):
		attrs = [
				self.stem,
				self.wordclass,
				self.pos,
				self.case2, 
				self.grade, 
				self.mood, 
				self.number, 
				self.personnumber,
				self.tense,
				self.attrsuffix,
				self.attributive, 
				self.soggi
			]
		attrs = [a for a in attrs if a]
		S = unicode('/'.join([a for a in attrs if a.strip()])).encode('utf-8')
		return S
	
	# def save(self, *args, **kwargs):
	# 	"""
	# 		Normalize syllables.
	# 	"""
	# 	syllables = {
	# 		'2syll': '2syll',
	# 		'3syll': '3syll',
	# 		'bisyllabic': '2syll',
	# 		'trisyllabic': '3syll',
	# 		'': '',
	# 	}
	# 	
	# 	if self.stem in syllables.keys():
	# 		self.stem = syllables[self.stem]
	# 	
	# 	super(Feedback, self).save(*args, **kwargs)
	


########### CONTEXT-MORFA, VASTA

class Question(models.Model):
	qid = models.CharField(max_length=200)
	level = models.IntegerField(max_length=3)
	task = models.CharField(max_length=20)
	string = models.CharField(max_length=200)
	qtype = models.CharField(max_length=20)
	qatype = models.CharField(max_length=20)
	question = models.ForeignKey('self', 
								 blank=True, 
								 null=True, 
								 related_name='answer_set')
	gametype = models.CharField(max_length=5)
	source = models.ManyToManyField(Source)
	def __unicode__(self):
		return self.string
	
class QElement(models.Model):
	"""
		QElements are individual elements of a question, such as a pronoun, subject, N-ACC, etc.
		They contain a set of WordQElements which represent each possible Word item in the database
		which could be filled in for a given slot in a question.
		
		WordQElements are filtered when installed by the database, as such there should be no need
		to filter in qagame (???)
		
		
	"""
	question = models.ForeignKey(Question, null=True)
	syntax = models.CharField(max_length=50)
	identifier = models.CharField(max_length=20)
	gametype = models.CharField(max_length=5)
	agreement = models.ForeignKey('self', 
								  blank=True,
								  null=True,
								  related_name='agreement_set')
	
	semtype = models.ForeignKey(Semtype, null=True) # ManyToMany instead?
	tags = models.ManyToManyField(Tag)
	game = models.CharField(max_length=20)
	copy = models.ForeignKey('self', 
							 blank=True,
							 null=True,
							 related_name='copy_set')
	def __unicode__(self):
		return self.question.string + ': ' + self.identifier

class WordQElement(models.Model):
	"""
		
	"""
	word = models.ForeignKey(Word, null=True)
	qelement = models.ForeignKey(QElement, null=True)
	#semtype = models.ForeignKey(Semtype, null=True)
	



######### EXTRA
class Grammarlinks(models.Model):
	name = models.CharField(max_length=200,blank=True,null=True)
	address = models.CharField(max_length=800,blank=True,null=True)
	language = models.CharField(max_length=5,blank=True,null=True)
