# Imports from standard libraries
from datetime import datetime

# Imports from Django
from django.db import models
from django.db.models import Q

# Imports from Brubeck
from brubeck.core.models import ContentChannel

def unique_slug(item,slug_source,slug_field):
    """Ensures a unique slug field by appending an integer counter to duplicate slugs.
    
    The item's slug field is first prepopulated by slugify-ing the source field. If that value already exists, a counter is appended to the slug, and the counter incremented upward until the value is unique.
    
    For instance, if you save an object titled Daily Roundup, and the slug daily-roundup is already taken, this function will try daily-roundup_2, daily-roundup_3, daily-roundup_4, etc, until a unique value is found.
    
    Call from within a model's custom save() method like so:
    unique_slug(item, slug_source='field1', slug_field='field2')
    where the value of field slug_source will be used to prepopulate the value of slug_field.
    """
    # Courtesy of http://www.djangosnippets.org/snippets/512/
    # Modified for use specifically with Event.
    
    if not getattr(item, slug_field): # if it's already got a slug, do nothing.
        from django.template.defaultfilters import slugify
        slug = slugify(getattr(item,slug_source))[:50]
        itemModel = item.__class__
        # the following gets all existing slug values
        allSlugs = [sl.values()[0] for sl in itemModel.objects.filter(start__year=item.start.year, start__month=item.start.month, start__day=item.start.day).values(slug_field)]
        if slug in allSlugs:
            import re
            counterFinder = re.compile(r'_\d+$')
            counter = 2
            slug = "%s_%i" % (slug, counter)
            if len(slug) > 50:      # Default SlugField max_length
                slug = re.sub(counterFinder, "", slug)
                suffix = "_%i" % counter
                slug = slug[:(50-len(suffix))]
                slug = "%s_%i" % (slug, counter)
            while slug in allSlugs:
                slug = re.sub(counterFinder,"_%i" % counter, slug)
                if len(slug) > 50:      # Default SlugField max_length
                    slug = re.sub(counterFinder, "", slug)
                    suffix = "_%i" % counter
                    slug = slug[:(50-len(suffix))]
                    slug = "%s_%i" % (slug, counter)
                counter += 1
        setattr(item,slug_field,slug)

class Calendar(ContentChannel):
    """
    Associates events with individual calendars.
    """
    last_updated = models.DateTimeField(blank=True, null=True, auto_now=True, help_text="When this calendar was last updated. The site will automatically update this field whenever the calendar is saved.")
    
    def __unicode__(self):
        return self.name
    def get_absolute_url(self):
        return '/calendar/%s/' % self.slug
    
    class Meta:
        ordering = ['name']

class NotPastManager(models.Manager):
    """
    Only returns events that aren't already over.
    """
    def get_query_set(self):
        return super(NotPastManager, self).get_query_set().filter(Q(end__gt=datetime.now()) | Q(end__isnull=True, start__gt=datetime.now()))

class Event(models.Model):
    """
    Maintains information about specific events.
    """
    name = models.CharField(max_length=150)
    summary = models.CharField(max_length=255, blank=True, help_text="A short description of the event.")
    description = models.TextField(blank=True, help_text="A longer description of the event. Accepts HTML (for embeds and such), but primarily uses <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> formatting. The basics:<ul><li>Separate paragraphs by blank lines.</li><li>Italicize words _like this_.</li><li>Make words (including subheads) bold **like this**.</li><li>Link things like so: Go to [themaneater.com](http://www.themaneater.com/).</li></ul>")
    start = models.DateTimeField(help_text="When does this event start?")
    end = models.DateTimeField(blank=True, null=True, help_text="When does this event end?")
    all_day = models.BooleanField(help_text="Does this event last all day? (If you check this box, the site will only pay attention to the start date (and the end date, if provided) and ignore the time. That said, the site won't let you add a date without a time, so just put <em>something</em> there.)")
    location = models.CharField(max_length=255, help_text="Where will this event take place?")
    calendars = models.ManyToManyField(Calendar, help_text="On which calendars should this event appear?")
    slug = models.SlugField(unique_for_date='start', blank=True, help_text="Used for URLs. Autogenerated from name.")
    last_updated = models.DateTimeField(blank=True, null=True, auto_now=True, help_text="When this event was last updated. The site will automatically update this field whenever the event is saved.")

    mediatype = 'event'
    
    objects = models.Manager()
    not_past = NotPastManager()
    
    def __unicode__(self):
        return self.name
    def get_absolute_url(self):
        return '/calendar/%s/%s/%s/%s/' % (self.start.year, self.start.month, self.start.day, self.slug)
    
    def save(self, *args, **kwargs):
        unique_slug(self, slug_source='name', slug_field='slug')
        super(Event, self).save(*args, **kwargs)
    
    class Meta:
        ordering = ['start', '-end']
