from django.db import models
from django.contrib.auth.models import User
from pgweb.util.bases import PgModel
from pgweb.util.misc import varnish_purge

from datetime import datetime

TESTING_CHOICES = (
	(0, 'Release'),
	(1, 'Release candidate'),
	(2, 'Beta'),
	)
TESTING_SHORTSTRING = ('', 'rc', 'beta')

class Version(PgModel, models.Model):
	tree = models.DecimalField(max_digits=3, decimal_places=1, null=False, blank=False, unique=True)
	latestminor = models.IntegerField(null=False, blank=False, default=0, help_text="For testing versions, latestminor means latest beta/rc number. For other releases, it's the latest minor release number in the tree.")
	reldate = models.DateField(null=False, blank=False)
	relnotes = models.CharField(max_length=32, null=False, blank=False)
	current = models.BooleanField(null=False, blank=False, default=False)
	supported = models.BooleanField(null=False, blank=False, default=True)
	testing = models.IntegerField(null=False, blank=False, default=0, help_text="Testing level of this release. latestminor indicates beta/rc number", choices=TESTING_CHOICES)
	docsloaded = models.DateTimeField(null=True, blank=True, help_text="The timestamp of the latest docs load. Used to control indexing and info on developer docs.")
	firstreldate = models.DateField(null=False, blank=False, help_text="The date of the .0 release in this tree")
	eoldate = models.DateField(null=False, blank=False, help_text="The planned EOL date for this tree")

	def __unicode__(self):
		return self.versionstring

	@property
	def versionstring(self):
		return self.buildversionstring(self.latestminor)

	def buildversionstring(self, minor):
		if not self.testing:
			return "%s.%s" % (self.tree, minor)
		else:
			return "%s%s%s" % (self.tree, TESTING_SHORTSTRING[self.testing], minor)

	@property
	def treestring(self):
		if not self.testing:
			return self.tree
		else:
			return "%s %s" % (self.tree, TESTING_SHORTSTRING[self.testing])

	def save(self):
		# Make sure only one version at a time can be the current one.
		# (there may be some small race conditions here, but the likelyhood
		# that two admins are editing the version list at the same time...)
		if self.current:
			previous = Version.objects.filter(current=True)
			for p in previous:
				if not p == self:
					p.current = False
					p.save() # primary key check avoids recursion

		# Now that we've made any previously current ones non-current, we are
		# free to save this one.
		super(Version, self).save()

	class Meta:
		ordering = ('-tree', )

	def purge_urls(self):
		yield '/$'
		yield '/support/submitbug'
		yield '/support/versioning'
		yield '/docs/$'
		yield '/docs/manuals'
		yield '/versions.rss'


class Country(models.Model):
	name = models.CharField(max_length=100, null=False, blank=False)
	tld = models.CharField(max_length=3, null=False, blank=False)

	class Meta:
		db_table = 'countries'
		ordering = ('name',)
		verbose_name = 'Country'
		verbose_name_plural = 'Countries'

	def __unicode__(self):
		return self.name

class Language(models.Model):
	# Import data from http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt
	# (yes, there is a UTF16 BOM in the UTF8 file)
	# (and yes, there is a 7 length value in a field specified as 3 chars)
	alpha3 = models.CharField(max_length=7, null=False, blank=False, primary_key=True)
	alpha3term = models.CharField(max_length=3, null=False, blank=True)
	alpha2 = models.CharField(max_length=2, null=False, blank=True)
	name = models.CharField(max_length=100, null=False, blank=False)
	frenchname = models.CharField(max_length=100, null=False, blank=False)

	class Meta:
		ordering = ('name', )

	def __unicode__(self):
		return self.name

	# Get the english language to use for default in foreign keys
	@staticmethod
	def english():
		return Language.objects.get(pk='eng')

class OrganisationType(models.Model):
	typename = models.CharField(max_length=32, null=False, blank=False)

	def __unicode__(self):
		return self.typename

class Organisation(PgModel, models.Model):
	name = models.CharField(max_length=100, null=False, blank=False, unique=True)
	approved = models.BooleanField(null=False, default=False)
	address = models.TextField(null=False, blank=True)
	url = models.URLField(null=False, blank=False)
	email = models.EmailField(null=False, blank=True)
	phone = models.CharField(max_length=100, null=False, blank=True)
	orgtype = models.ForeignKey(OrganisationType, null=False, blank=False, verbose_name="Organisation type")
	managers = models.ManyToManyField(User, null=False, blank=False)
	lastconfirmed = models.DateTimeField(null=False, blank=False, default=datetime.now())

	send_notification = True

	def __unicode__(self):
		return self.name

	class Meta:
		ordering = ('name',)


# Basic classes for importing external RSS feeds, such as planet
class ImportedRSSFeed(models.Model):
	internalname = models.CharField(max_length=32, null=False, blank=False, unique=True)
	url = models.URLField(null=False, blank=False)
	purgepattern = models.CharField(max_length=512, null=False, blank=True, help_text="NOTE! Pattern will be automatically anchored with ^ at the beginning, but you must lead with a slash in most cases - and don't forget to include the trailing $ in most cases")

	def purge_related(self):
		if self.purgepattern:
			varnish_purge(self.purgepattern)

	def __unicode__(self):
		return self.internalname

class ImportedRSSItem(models.Model):
	feed = models.ForeignKey(ImportedRSSFeed)
	title = models.CharField(max_length=100, null=False, blank=False)
	url = models.URLField(null=False, blank=False)
	posttime = models.DateTimeField(null=False, blank=False)

	def __unicode__(self):
		return self.title

	@property
	def date(self):
		return self.posttime.strftime("%Y-%m-%d")


# Extra attributes for users (if they have them)
class UserProfile(models.Model):
	user = models.ForeignKey(User, null=False, blank=False, unique=True, primary_key=True)
	sshkey = models.TextField(null=False, blank=True, verbose_name="SSH key", help_text= "Paste one or more public keys in OpenSSH format, one per line.")
	lastmodified = models.DateTimeField(null=False, blank=False, auto_now=True)

# Notifications sent for any moderated content.
# Yes, we uglify it by storing the type of object as a string, so we don't
# end up with a bazillion fields being foreign keys. Ugly, but works.
class ModerationNotification(models.Model):
	objectid = models.IntegerField(null=False, blank=False, db_index=True)
	objecttype = models.CharField(null=False, blank=False, max_length=100)
	text = models.TextField(null=False, blank=False)
	author = models.CharField(null=False,  blank=False, max_length=100)
	date = models.DateTimeField(null=False, blank=False, auto_now=True)

	def __unicode__(self):
		return "%s id %s (%s): %s" % (self.objecttype, self.objectid, self.date, self.text[:50])

	class Meta:
		ordering = ('-date', )
