import os
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.utils.functional import cached_property
from django.utils.text import get_valid_filename

from personalni.models import Organizator

import subprocess
from reversion import revisions as reversion

from unidecode import unidecode


def generate_filename(self, filename):
	""" vyrobí jméno souboru podle původního jména a času nahrátí """
	clean = get_valid_filename(
		unidecode(
			filename.replace('/', '-').replace('\0', '').replace(":", "_")
		)
	)
	fname = "%s_%s" % (
		timezone.now().strftime('%Y-%m-%d-%H_%M'),
		clean)
	return os.path.join(settings.KOREKTURY_PDF_DIR, fname)

#@reversion.register(ignore_duplicates=True)
class KorekturovanePDF(models.Model):
	class Meta:
		ordering = ['-cas']
		db_table = 'korekturovane_cislo'
		verbose_name = u'PDF k opravám'
		verbose_name_plural = u'PDF k opravám'
	
	#Interní ID
	id = models.AutoField(primary_key = True)

	cas = models.DateTimeField(u'čas vložení PDF',default=timezone.now,help_text = 'Čas vložení PDF')

	nazev = models.CharField(u'název PDF',blank = False,max_length=50, help_text='Název (např. `22.1 | analyza v4` nebo `propagace | letacek v0`) korekturovaného PDF')

	komentar = models.TextField(u'komentář k PDF',blank = True, help_text='Komentář ke korekturovanému PDF (např. na co se zaměřit)')

	pdf = models.FileField(u'PDF', upload_to = generate_filename)

	orgove = models.ManyToManyField(Organizator, blank=True,
		help_text='Zodpovědní organizátoři za obsah (chodí jim maily o nových korekturách)',
		default=None)

	stran = models.IntegerField(u'počet stran', help_text='Počet stran PDF',
								default=0)
	STATUS_PRIDAVANI = 'pridavani'
	STATUS_ZANASENI = 'zanaseni'
	STATUS_ZASTARALE = 'zastarale'
	STATUS_CHOICES = (
			(STATUS_PRIDAVANI, u'Přidávání korektur'),
			(STATUS_ZANASENI, u'Korektury jsou zanášeny'),
			(STATUS_ZASTARALE, u'Stará verze, nekorigovat'),
			)
	status = models.CharField(u'stav PDF',max_length=16, choices=STATUS_CHOICES, blank=False,
			default = STATUS_PRIDAVANI)

	poslat_mail = models.BooleanField('Poslat mail o novém PDF', default=True,
			help_text='Určuje, zda se má o nově nahraném PDF poslat e-mail do mam-org. Při upravování existujícího souboru už nemá žádný vliv.',
			)


	#TODO Nepovinný foreign key k číslu

	def get_prefix(self):
		"""Vrať řetězec, ke kterému se připojí číslo a .png"""
		# vrátíme jméno souboru bez cesty
		return os.path.basename(self.pdf.file.name)

	def convert(self):
		"""Vytvoří jedno png za každou stranu pdf a uloží se"""
		dirname = os.path.join(settings.MEDIA_ROOT, settings.KOREKTURY_IMG_DIR)
		if not os.path.exists(dirname):
			os.mkdir(dirname)
		self.stran = 0
		while True:
			res = subprocess.call([
				#Parametry inspirovány chybovou hláškou imagemagicku
				"gs",
				"-sstdout=%stderr",
				"-dSAFER",
				"-dNOPAUSE",
				"-dBATCH",
				"-dNOPROMPT",
				"-sDEVICE=pngalpha",
				"-r180x180",
				"-dFirstPage=%d" % (self.stran+1),
				"-dLastPage=%d" % (self.stran+1),
				"-sOutputFile="+os.path.join(
					dirname,
					"%s-%d.png" % (self.get_prefix(), self.stran)),
				"-f%s" % (self.pdf.path)
			])
			if not os.path.exists(os.path.join(
					dirname,
					"%s-%d.png" % (self.get_prefix(), self.stran))):
				break
			self.stran += 1
		# Změnil se počet stran, ukládáme
		super(KorekturovanePDF, self).save()

	def save(self, **kwargs):
		# Pokud se nezmenilo PDF, tak nepregenerovavej nahledy
		try:
			original = KorekturovanePDF.objects.get(pk=self.pk)
			if original.pdf == self.pdf:
				super(KorekturovanePDF, self).save()
				return
		except ObjectDoesNotExist:
			pass
		# uložíme nahrávané pdf
		super(KorekturovanePDF, self).save(kwargs)

		# uložíme png a změněný počet stran
		self.convert()

	@cached_property
	def cislo_a_tema(self):
		nazev_split = self.nazev.split()
		try:
			return nazev_split[0]  # + " " + nazev_split[2]
		except IndexError:
			return self.nazev
	
	def get_absolute_url(self):
		return reverse('korektury', kwargs={'pdf': self.id})


@reversion.register(ignore_duplicates=True)
class Oprava(models.Model):
	class Meta:
		db_table = 'opravy'
		verbose_name = u'Oprava'
		verbose_name_plural = u'Opravy'
		ordering = ['y','x']
	
	#Interní ID
	id = models.AutoField(primary_key = True)

	pdf = models.ForeignKey(KorekturovanePDF, default=-1, on_delete=models.PROTECT)

	strana = models.IntegerField(u'strana s opravou', help_text='Strana s opravou (od 0)')

	x = models.IntegerField(u'x-ová souřadnice bugu')
	y = models.IntegerField(u'y-ová souřadnice bugu')

	STATUS_K_OPRAVE = 'k_oprave'
	STATUS_OPRAVENO = 'opraveno'
	STATUS_NENI_CHYBA = 'neni_chyba'
	STATUS_K_ZANESENI = 'k_zaneseni'
	STATUS_CHOICES = (
			(STATUS_K_OPRAVE, u'K opravě'),
			(STATUS_OPRAVENO, u'Opraveno'),
			(STATUS_NENI_CHYBA, u'Není chyba'),
			(STATUS_K_ZANESENI, u'K zanesení do TeXu'),
			)
	status = models.CharField(u'stav opravy',max_length=16, choices=STATUS_CHOICES, blank=False,
			default = STATUS_K_OPRAVE)

	autor = models.ForeignKey(Organizator, blank = True,
			help_text='Autor opravy',
			null = True, on_delete=models.SET_NULL)
	
	text = models.TextField(u'text opravy',blank = True, help_text='Text opravy')

#	def __init__(self,dictionary):
#		for k,v in dictionary.items():
#			setattr(self,k,v)

	def __str__(self):
		return '{} od {}: {}'.format(self.status,self.autor,self.text)



@reversion.register(ignore_duplicates=True)
class Komentar(models.Model):
	class Meta:
		db_table = 'komentare'
		verbose_name = u'Komentář k opravě'
		verbose_name_plural = u'Komentáře k opravě'
		ordering = ['cas']
	
	#Interní ID
	id = models.AutoField(primary_key = True)

	cas = models.DateTimeField(u'čas komentáře',default=timezone.now,help_text = 'Čas zadání komentáře')

	oprava = models.ForeignKey(Oprava, on_delete=models.CASCADE)
	autor = models.ForeignKey(Organizator, blank = True,
			help_text = u'Autor komentáře',
			null = True, on_delete=models.SET_NULL)
	
	text = models.TextField(u'text komentáře',blank = True, help_text='Text komentáře')

	def __str__(self):
		return '{} od {}: {}'.format(self.cas,self.autor,self.text)