from django import forms
from dal import autocomplete
from django.forms import formset_factory
from django.forms.models import inlineformset_factory
from django.utils import timezone

from personalni.models import Resitel
from tvorba.models import Problem, Deadline
from various.models import Nastaveni

from odevzdavatko.models import Reseni, PrilohaReseni, Hodnoceni

import logging

# pro přidání políčka do formuláře je potřeba
# - mít v modelu tu položku, kterou chci upravovat
# - přidat do views (prihlaskaView, resitelEditView)
# - přidat do forms
# - includovat do html

class DateInput(forms.DateInput):
    # aby se datum dalo vybírat z kalendáře
    input_type = 'date' 


class PosliReseniForm(forms.Form):
	problem = forms.ModelMultipleChoiceField(
		queryset=Problem.objects.all(),
		label="Problémy",
		widget=autocomplete.ModelSelect2Multiple(
			url='autocomplete_problem',
			attrs={
				'data-placeholder--id': '-1',
				'data-placeholder--text': '---',
				'data-close-on-select': 'false',
				'data-dropdown-css-class': 's2m-se-zaskrtavatky',
				'data-allow-clear': 'true'
				},
			),
	)
	# to_field_name
	#problem = models.ManyToManyField(Problem, verbose_name='problém', help_text='Problém',
	#	through='Hodnoceni')

	resitel = forms.ModelMultipleChoiceField(label="Řešitelé",
		queryset=Resitel.objects.all(),
		widget=autocomplete.ModelSelect2Multiple(
			url='autocomplete_resitel',
			attrs = {'data-placeholder--id': '-1',
				'data-placeholder--text' : '---',
				'data-close-on-select': 'false',
				'data-dropdown-css-class': 's2m-se-zaskrtavatky',
				'data-allow-clear': 'true'})
    		)


	#resitele = models.ManyToManyField(Resitel, verbose_name='autoři řešení',
	#	help_text='Seznam autorů řešení', through='Reseni_Resitele')
	
	cas_doruceni = forms.DateField(widget=DateInput(),label="Čas doručení")

	#cas_doruceni = models.DateTimeField('čas_doručení', default=timezone.now, blank=True)

	forma = forms.ChoiceField(label="Forma řešení",choices = Reseni.FORMA_CHOICES)
	#forma = models.CharField('forma řešení', max_length=16, choices=FORMA_CHOICES, blank=False,
	#	 default=FORMA_EMAIL)

	poznamka = forms.CharField(label='Neveřejná poznámka', required=False)
	#poznamka = models.TextField('neveřejná poznámka', blank=True,
	#	help_text='Neveřejná poznámka k řešení (plain text)')


class NahrajReseniForm(forms.ModelForm):
	class Meta:
		model = Reseni
		fields = ('problem', 'resitele')
		help_texts = {'problem':''} # Nezobrazovat help text ve formuláři
		
		widgets = {'problem':
				autocomplete.ModelSelect2Multiple(
					url='autocomplete_problem_odevzdatelny',
					attrs = {'data-placeholder--id': '-1',
						'data-placeholder--text' : '---',
						'data-close-on-select': 'false',
						'data-dropdown-css-class': 's2m-se-zaskrtavatky',
						'data-allow-clear': 'true'},
					forward=["nadproblem_id"],
				),
				'resitele':
				autocomplete.ModelSelect2Multiple(
					url='autocomplete_resitel_public',
					attrs = {'data-placeholder--id': '-1',
						'data-placeholder--text' : '---',
						'data-close-on-select': 'false',
						'data-dropdown-css-class': 's2m-se-zaskrtavatky',
						'data-allow-clear': 'true'},
				)
		}

	nadproblem_id = forms.IntegerField(required=False, disabled=True, widget=forms.HiddenInput())

	def __init__(self, *args, **kwargs):
		super().__init__(*args, **kwargs)
		# FIXME Z nějakého důvodu se do této třídy dostaneme i bez resitele
		if 'resitele' in self.fields:
			# FIXME Mnohem hezčí by to bylo u definice resitele výše, ale nepodařilo se mi to.
			self.fields['resitele'].required = False
			self.fields['resitele'].label = "Další autoři"
		if 'problem' in self.fields:
			self.fields['problem'].label = "Všechny řešené problémy"

	def clean_problem(self):
		problem = self.cleaned_data.get('problem')
		for p in problem:
			if p.stav != Problem.STAV_ZADANY:
				raise forms.ValidationError("Problém " + str(p) + " již nelze řešit!")
		return problem

ReseniSPrilohamiFormSet = inlineformset_factory(Reseni, PrilohaReseni,
		form = NahrajReseniForm,
		fields = ('soubor','res_poznamka'),
		widgets = {'res_poznamka':forms.TextInput()},
		extra = 1,
		can_delete = False,

		)


class JednoHodnoceniForm(forms.ModelForm):
	class Meta:
		model = Hodnoceni
		fields = ('problem', 'body', 'deadline_body', 'feedback',)
		widgets = {
			'problem': autocomplete.ModelSelect2(
				url='autocomplete_problem',
				),
			'feedback': forms.Textarea(attrs={'rows': 1, 'cols': 30, 'class': 'feedback'}),
			}

	body_celkem = forms.DecimalField(required=False, decimal_places=1)
	body_neprepocitane = forms.DecimalField(required=False, decimal_places=1)
	body_neprepocitane_celkem = forms.DecimalField(required=False, decimal_places=1)

	def __init__(self, *args, initial=None, **kwargs):
		if initial is not None:
			body_max = initial["body_max"]
			body_neprepocitane_max = initial["body_neprepocitane_max"]
			del(initial["body_max"])
			del(initial["body_neprepocitane_max"])
		super().__init__(*args, initial=initial, **kwargs)
		if initial is not None:
			self.fields['body'].widget.attrs['placeholder'] = body_max
			self.fields['body_celkem'].widget.attrs['placeholder'] = body_max
			self.fields['body_neprepocitane'].widget.attrs['placeholder'] = body_neprepocitane_max
			self.fields['body_neprepocitane_celkem'].widget.attrs['placeholder'] = body_neprepocitane_max


OhodnoceniReseniFormSet = formset_factory(JednoHodnoceniForm,
		extra = 0,
		)

class PoznamkaReseniForm(forms.ModelForm):
	class Meta:
		model = Reseni
		fields = ('poznamka',)

# FIXME: Ideálně by mělo být součástí třídy níž, ale neumím to udělat
DATE_FORMAT = '%Y-%m-%d'

class OdevzdavatkoTabulkaFiltrForm(forms.Form):
	"""Form pro filtrování přehledové odevzdávátkové tabulky

	Inspirováno https://kam.mff.cuni.cz/mffzoom/"""

	# Věci definované níž se importují i ve views pro odevzdávátko (Inspirováno https://docs.djangoproject.com/en/3.1/ref/models/fields/#field-choices)

	RESITELE_RELEVANTNI = 'relevantni'
	RESITELE_NEODMATUROVAVSI = 'neodmaturovavsi'
	RESITELE_CHOICES = [
		(RESITELE_RELEVANTNI, 'Relevantní řešitelé'), # I.e. nezobrazovat prázdné řádky tabulky
		(RESITELE_NEODMATUROVAVSI, 'Všichni bez maturity'),
		# Možná: všechny vč. historických?
		]

	PROBLEMY_MOJE = 'moje'
	PROBLEMY_LETOSNI = 'letosni'
	PROBLEMY_CHOICES = [
		(PROBLEMY_MOJE, 'Moje problémy'), # Letošní problémy, které mají v sobě nebo v nadproblémech přiřazeného daného orga
		(PROBLEMY_LETOSNI, 'Všechny letošní'),
		# TODO: *hlavní problémy, možná všechny...
		# XXX: Chtělo by to i "aktuálně zadané...
		]

	# TODO: Typy problémů (problémy, úlohy, ostatní, všechny)? Jen některá řešení (obodovaná/neobodovaná, víc řešitelů, ...)?


	@classmethod
	def gen_terminy(cls, rocnik=None):
		import datetime
		from time import strftime
		
		from django.db.utils import OperationalError
		try:
			aktualni_rocnik = Nastaveni.get_solo().aktualni_rocnik
		except OperationalError:
			# django.db.utils.OperationalError: no such table: seminar_nastaveni
			# Nemáme databázi, takže to selhalo. Pro jistotu vrátíme aspoň dvě možnosti, ať to nepadá dál
			logger = logging.getLogger(__name__)
			logger.error("Rozbitá databáze (před počátečními migracemi?)")
			return [('broken', 'Je to rozbitý'), ('fubar', 'Nefunguje to')]

		# FIXME: Tohle je hnusný monkey patch, mělo by to být nějak zahrnuto výš.
		if rocnik is not None:
			aktualni_rocnik = rocnik

		result = []

		result.append(("0001-01-01", f"Odjakživa"))

		for deadline in Deadline.objects.filter(
				deadline__lte=timezone.now(),
				cislo__rocnik=aktualni_rocnik
				).order_by("deadline"):

			result.append((
				strftime(DATE_FORMAT, deadline.deadline.timetuple()),
				str(deadline)))

		result.append((
			strftime(DATE_FORMAT, datetime.date.today().timetuple()), f"Dnes"))

		return result

	@classmethod
	def gen_initial(cls, rocnik=None):
		terminy = cls.gen_terminy(rocnik)
		initial = {
			'resitele': cls.RESITELE_RELEVANTNI,
			'problemy': cls.PROBLEMY_MOJE,
			# Pokud chceme neaktuální ročník, tak nás nejspíš zajímají všechna řešení…
			'reseni_od': terminy[-2] if rocnik is None else terminy[0],
			'reseni_do': terminy[-1],
			'neobodovane': False,
			'barvicky': True,
		}
		return initial

	def __init__(self, *args, rocnik=None, **kwargs):
		if 'initial' not in kwargs:
			super().__init__(initial=self.gen_initial(rocnik), *args, **kwargs)
		else:
			super().__init__(*args, **kwargs)
		# choices jako parametr Select widgetu neumí brát callable, jen iterable, takže si pro jednoduchost můžu rovnou uložit výsledek sem...
		# A "sem" znamená do libovolné metody, protože jinak se jedná o kód, který django spustí při inicializaci a protože potřebujeme databázi, tak by spadnul při vyrábění testdat...
		self.terminy = self.gen_terminy(rocnik)
		self.fields['reseni_od'].widget = forms.Select(choices=self.gen_terminy(rocnik))
		# Pokud chceme neaktuální ročník, tak nás nejspíš zajímají všechna řešení…
		self.fields['reseni_od'].initial = self.terminy[-2] if rocnik is None else self.terminy[0]
		self.fields['reseni_do'].widget = forms.Select(choices=self.gen_terminy(rocnik))
		self.fields['reseni_do'].initial = self.terminy[-1]

	# NOTE: Initial definuji pro jednotlivé fieldy, aby to bylo tady a nebylo potřeba to řešit ve views...
	resitele = forms.ChoiceField(choices=RESITELE_CHOICES)
	problemy = forms.ChoiceField(choices=PROBLEMY_CHOICES)
	
	reseni_od = forms.DateField(input_formats=[DATE_FORMAT])
	reseni_do = forms.DateField(input_formats=[DATE_FORMAT])
	neobodovane = forms.BooleanField(required=False)
	barvicky = forms.BooleanField(required=False)