from django import forms
from django.utils.translation import ugettext as _

from drill.forms import GameSettings, Question
from drill.models import Word, WordTranslation

from gamesettings.yamltools import yget

from django.db.models import Q, Count

YAML_SAMPLE = """
Leksa:
  questions:
    - question:
        model: 'Word'
        attribute: 'lemma'
      answer: 
        model: 'WordTranslation'
        attribute: 'definition'
  taxonomy:
    - "languagepairs":
      model: 'Word'
      attribute: 'language'
      - "semtypes":
      model: 'Word'
      attribute: 'semtype__semtype'
  languagepairs:
    - ["sma", "nob"]
  semtypes:
    - ['HUMAN', 'Human']
"""


class YAMLSettings(object):
	def get(self, path):
		return yget(self.yamldict, path)

	def toGetTextTuples(self, opts):
		return [(a, _(b)) for a, b in opts]


	def taxonomies(self):
		taxes = self.yamldict['taxonomy']
		choices = {}
		taxonomies = {}

		for tax, opts in taxes.items():
			proc_opts = self.toGetTextTuples(opts['choices'])
			self.__setattr__(tax, proc_opts)
			taxonomies[tax] = proc_opts

		self.choices = choices
		self.taxonomies = taxonomies

	def questionAnswer(self):
		QAs = self.yamldict['questions']
		
		QA = []
		for item in QAs:
			pass


	def __init__(self, fname, gamename):
		
		import yaml
		with open(fname, 'r') as F:
			data = F.read()
			config_data = yaml.load(data)

		self.yamldict = config_data[gamename] or False
		self.taxonomies()
		
		# parse YAML
		# question sets
		# taxonomies (create objects to set forms) 

import settings as S

yfile = S.GAME_SETTINGS

class LeksaSettings(GameSettings):
	""" Leksa settings form.
	
		TODO: Method to set session data according to settings.
	
	"""

	select = {'widget': forms.Select}

	def __init__(self, *args, **kwargs):
		gametype = type(self).__name__ # Leksa
		self.yaml = YAMLSettings(yfile, gametype)
		
		if 'preset_fields' in kwargs:
			preset_fields = kwargs['preset_fields']
		else:
			preset_fields = {}
		
		for tax, opts in self.yaml.taxonomies.items():
			t = self.yaml.get('taxonomy/%s' % tax)

			if 'choices' in t:
				fieldtype = forms.ChoiceField

			preset_fields[tax] = fieldtype(initial=opts[0][0],
											choices=opts,
											**self.select)
			# self.__setattr__(tax, field)
		kwargs['preset_fields'] = preset_fields
		super(LeksaSettings, self).__init__(*args, **kwargs)
	
	def makeQuery(self):
		if self.is_valid():
			options = self.cleaned_data
		else:
			options = self.initial_data
		
		for tax, opts in self.yaml.taxonomies.items():
			t = self.yaml.get('taxonomy/%s' % tax)
			qkwargs = {}
			if tax in options:
				qkwargs[t['attr']] = options[tax]

		QUERY = Q(**qkwargs)

		self.query = QUERY
		return True
	
	def getInitialData(self):
		""" Get initial data to populate formsets.
		"""
		if self.is_valid():
			options = self.cleaned_data
		else:
			options = self.initial_data

		answer_language = options['transtype'][-3::]
		question_language = options['transtype'][0:3]

		initialwords = Word.objects.filter(language=question_language, wordtranslation__language=answer_language)

		initialwords = initialwords.filter(self.query)\
						.order_by('?')[0:self.question_count]
		
		inits = []
		for word in initialwords:
			xls = word.wordtranslation_set.filter(language=answer_language)
			translations = [x.definition for x in xls if x.definition.strip()]
			app = {
				'id': word.id,
				'lemma': word.lemma,
				'translations': translations}
			inits.append(app)

		return inits

class Leksa(LeksaSettings):
	pass

class LeksaPlace(LeksaSettings):
	pass

class LeksaQuestion(Question):
	""" This is the Leksa question class. It produces only one question,
		and has methods to validate whether this question is correct or not.
		
		Incorrect answers throw validation errors and provide a reason as the
		error message.
		
		This question should be used in a Formset.

		Most of the functionality is in the Question parent class, except for 
		check_anwer.
	
	"""
	
	def check_answer(self):
		""" Check answers.
		
			TODO: Turn this into a validator.
		
		"""
		answers = self.cleaned_data.get("answers")
		user_answer = self.cleaned_data.get("userans")
		
		if answers:
			if user_answer not in answers:
				self._errors["userans"] = self.Errors.try_again
				self.correct = False
			else:
				self.correct = True
		else:
			self._errors = self.Errors.empty_answers
		
		if not user_answer:
			self._errors["userans"] = self.Errors.blank_user_answer
		
		return

