import logging

from django.contrib.auth.models import User
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext_lazy as _
from tagging.models import Tag

from mbed.comlibs.models import ContentItem, MollomContent
from mbed.questions.models import Question


class Wiki(models.Model):
    name = models.CharField(_('name'), max_length=255)
    slug = models.CharField(_('slug'), max_length=255)
    allow_page_comments = models.BooleanField(default=False)
    subscribers = models.ManyToManyField(User, related_name='wiki_subscribers', verbose_name=_('Subscribers'), blank=True)
    public = models.BooleanField(default=True)

    #the object this wiki is attached to
    content_type = models.ForeignKey(ContentType, related_name="wiki_relation", null=True, blank=True)
    object_id = models.PositiveIntegerField(null=True, blank=True)
    content_object = generic.GenericForeignKey('content_type', 'object_id') #pseudo database field

    def get_absolute_url(self):
        if self.content_object:
            if self.content_type.__unicode__() == 'repository':
                return self.content_object.get_absolute_url() + 'wiki/'
            elif self.content_type.__unicode__() == 'mbed group':
                return self.content_object.get_absolute_url() + 'wiki/'
        return '/%s/'%self.slug

    def __unicode__(self):
        return "Wiki: " + self.slug

    @classmethod
    def private_repo_check(self):
        wikis = Wiki.objects.all()
        for wiki in wikis:
            if wiki.get_content_type() == 'repository':
                try:
                    if wiki.content_object.public == False:
                        wiki.public = False
                        wiki.save(no_update_dates=True)
                except:
                    print wiki
                    print wiki.content_object
                    pass

    def get_content_type(self):
        return str(self.content_type)

    def save(self, *args, **kwargs):
        if self.get_content_type() == 'repository':
            if self.content_object.public == False:
                self.public = False
            else:
                self.public = True
        super(Wiki, self).save(*args, **kwargs)

    def get_permissions(self, user, use_group=True):
        if self.content_object and self.content_type.__unicode__() in ('repository', 'mbed group'):
            return self.content_object.get_permissions(user, use_group=use_group)

        #fall back to granular perms mechanism
        from mbed.comlibs import util
        return util.get_permissions(user, self, skip=True, use_group=use_group)


class WikiPage(ContentItem, MollomContent):
    wiki = models.ForeignKey(Wiki, related_name='wiki')
    slug = models.CharField(_('slug'), max_length=255)
    subscribers = models.ManyToManyField(User, related_name='wikipage_subscribers', verbose_name=_('Subscribers'), blank=True)
    allow_comments = models.BooleanField(default=False)
    view_counter = models.PositiveIntegerField(default=0)
    hidelog = models.BooleanField(default=False)

    class Meta:
        ordering = ['slug']

    def __unicode__(self):
        return self.get_seo_slug()

    def save(self, *args, **kwargs):
        if self.wiki.get_content_type() == 'repository':
            if self.wiki.content_object.public == False:
                self.wiki.public = False
            else:
                self.wiki.public = True
        super(WikiPage, self).save(*args, **kwargs)

    @property
    def current(self):
        try:
            return self.revisions.latest()
        except:
            return None

    @property
    def name(self):
       return self.get_seo_slug().decode("utf-8")

    @property
    def rev(self, rev_id):
        return self.revisions.get(pk=rev_id)

    def get_absolute_url(self):
        return self.wiki.get_absolute_url() + self.slug

    def get_parent(self):
        if '/' in self.slug:
            return self.slug.split('/')[0]

    def get_seo_slug(self):
        return self.slug.replace('-', ' ')

    def has_edit_perms(self, user):
        #a helper for use in templates
        return user.has_row_perm(self.wiki, 'edit')

    def get_related_questions(self):
        return Question.objects.filter(object_id=self.id, content_type=ContentType.objects.get_for_model(self) ).order_by('-created')

    @property
    def strtags(self):
        # TODO: Use tags mixin.
        return ' '.join([b['name'] for b in Tag.objects.get_for_object(self).values()])

    def get_permissions(self, user, use_group=True):
        return self.wiki.get_permissions(user, use_group=use_group)


class Revision(ContentItem):
    page = models.ForeignKey(WikiPage, related_name='revisions')
    message = models.TextField(_('change message'), blank=True)
    content = models.TextField(_('Content'), blank=True)

    class Meta:
        ordering = ['-updated']
        get_latest_by = 'updated'

    def __unicode__(self):
        return 'Revision of %s at %s' % (self.page.slug, self.created.strftime('%x %X'))

    def get_absolute_url(self):
        return reverse('wiki:wakawaka_page', kwargs={'slug': self.page.slug}, current_app=self.page.wiki.slug)

    def render(self):
        from wakawaka.util import render
        return render(self.content)


def get_diff_to_rev(rev_to=None, rev_from=None):
    import difflib
    page = rev_to.page
    post_plaintext = ''
    text = ''

    #get previous rev
    try:
        if not rev_from:
            rev_from = Revision.objects.filter(page=page).order_by('-created')[1:][0]
        d = difflib.unified_diff(
            rev_from.content.splitlines(),
            rev_to.content.splitlines(),
            'Original',
            'Current',
            lineterm=''
        )
        diff = [a for a in d]
        post_plaintext = '\n'.join(diff)
        text = '<br/>'.join(diff)
    except IndexError:
        #there was no revision to diff
        post_plaintext = '\n'.join(rev_to.content.splitlines())
        text = '<br/>'.join(rev_to.content.splitlines())

    return text
