# -*- coding: utf-8 -*-
from os import path

from django.conf import settings
from django.utils.timezone import now
from django.core.urlresolvers import reverse
from django.core.cache import cache
from django.db import models
from django.template.defaultfilters import slugify
from django.utils.safestring import mark_safe
from django.utils.translation import get_language, ugettext as _
from django.core.exceptions import ValidationError
from ckeditor.fields import RichTextField


from kasu.image_models import ImageModel
from utils import STATUS_CHOICES, STATUS_WAITING, STATUS_PUBLISHED, \
    cleaner


CONTENT_CHOICES = (
    (0, u'Django View'),
    (1, u'HTML'),
    (2, u'PDF')
)


def get_upload_path(instance, filename):
    """
    Generates the desired file path and filename for an uploaded Image.
    With this function Django can save the uploaded images to subfolders that
    also have a meaning for humans.

    @param instance: an Django Object for which the Image has been uploaded.
    @type instance: a instace of an models.Model sub-class.
    @param filename: The filename of the uploaded image.
    @type filename: String
    """
    extension = filename[filename.rfind('.') + 1:]
    if isinstance(instance, Category):
        return "categories/%s.%s" % (instance.slug, extension)


class ArticleManager(models.Manager):
    def published(self):
        return self.filter(status=STATUS_PUBLISHED, date_created__lte=now())


class Article(ImageModel):
    headline_de = models.CharField(_('Headline'), max_length=255)
    headline_en = models.CharField('Headline', max_length=255, blank=True)
    content_de = RichTextField(_('Content'))
    content_en = RichTextField('Content', blank=True)
    category = models.ForeignKey('Category', verbose_name=_('Category'))
    image = models.ImageField(_('Image'), upload_to='news/',
                              blank=True, null=True)
    slug = models.SlugField(_('Slug'), unique_for_month='date_created')
    author = models.ForeignKey(settings.AUTH_USER_MODEL,
                               verbose_name=_('Author'))
    status = models.SmallIntegerField(_('Status'), choices=STATUS_CHOICES,
                                      default=STATUS_PUBLISHED)
    date_created = models.DateTimeField(_('Created'), blank=True)
    date_modified = models.DateTimeField(_('Modified'), auto_now=True)
    objects = ArticleManager()

    class Meta(object):
        verbose_name = _('Article')
        verbose_name_plural = _('Articles')
        ordering = ('-date_created',)

    def clean(self):
        if not self.date_created:
            self.date_created = now()
        if not self.slug:
            self.slug = slugify(self.headline_de)[:50]
        self.content_de = cleaner.clean_html(self.content_de)
        self.content_en = cleaner.clean_html(self.content_en)

    def __unicode__(self):
        return self.headline

    @property
    def posting_image(self):
        if self.image:
            return self.article
        else:
            return self.category.article

    def get_absolute_url(self):
        kwargs = {
            'year': self.date_created.strftime('%Y'),
            'month': self.date_created.strftime('%m'),
            'slug': self.slug,
        }
        return reverse('show-article', kwargs=kwargs)

    @property
    def headline(self):
        headline = getattr(self, "headline_%s" % get_language())
        if not headline:
            return mark_safe(self.headline_de)
        else:
            return mark_safe(headline)

    @property
    def content(self):
        content = getattr(self, "content_%s" % get_language(), self.content_de)
        if not content:
            return mark_safe(self.content_de)
        else:
            return mark_safe(content)


class Page(models.Model):
    """
    Eine Seite auf der Homepage. Sie kann eine "statische" HTML Seite,
    die URL einer dynamische Django View, oder ein PDF Dokument sein.
    Jede Seite kann neben Deutsch auch auf Englisch angeboten werden.
    Ist keine englische Übersetzung vorhanden, wird die deutsche Version
    angeboten.
    """
    menu_name_de = models.CharField(
        'Menü Name',
        max_length=255,
        help_text=_('The short name for the menu-entry of this page')
    )
    menu_name_en = models.CharField(
        'Menu Name',
        max_length=255,
        blank=True,
        help_text=_('The short name for the menu-entry of this page')
    )
    title_de = models.CharField('Titel', max_length=255,
                                help_text=_(
                                    'This title appears in the HTML header'))
    title_en = models.CharField('Title', max_length=255, blank=True,
                                help_text=_(
                                    'This title appears in the HTML header'))
    slug = models.SlugField(_('slug'))
    path = models.CharField(_('Path'), max_length=100, db_index=True,
                            editable=False, unique=True)

    parent = models.ForeignKey('self', blank=True, null=True,
                               related_name='subpages',
                               on_delete=models.SET_NULL)
    position = models.PositiveSmallIntegerField(_('Position'),
                                                blank=True, null=True)
    status = models.SmallIntegerField(_('status'), choices=STATUS_CHOICES,
                                      default=STATUS_WAITING)
    content_type = models.IntegerField(choices=CONTENT_CHOICES)

    content_de = RichTextField('Inhalt', blank=True)
    content_en = RichTextField('Content', blank=True)
    enable_comments = models.BooleanField(_('enable comments'), default=True)
    template = models.CharField(_('Template'), max_length=100,
                                default="content/page.html")
    pdf_de = models.FileField(upload_to='pdf/de/', blank=True, null=True)
    pdf_en = models.FileField(upload_to='pdf/en/', blank=True, null=True)

    def __unicode__(self):
        return u'%s' % self.title

    @property
    def content(self):
        cont = getattr(self, "content_%s" % get_language()) or self.content_de
        return mark_safe(cont)

    @property
    def css_class(self):
        return CONTENT_CHOICES[self.content_type][1].lower().replace(' ', '_')

    @property
    def menu_name(self):
        return getattr(self,
                       "menu_name_%s" % get_language()) or self.menu_name_de

    @property
    def pdf_file(self):
        return getattr(self, "pdf_%s" % get_language()) or self.pdf_de

    @property
    def title(self):
        return getattr(self, "title_%s" % get_language()) or self.title_de

    def clean(self):
        if self.parent is None:
            self.path = self.slug
        else:
            self.path = path.join(self.parent.path, self.slug)

        if self.content_type is None:
            if self.pdf_de:
                self.content_type = 2
            if self.content_de:
                self.content_type = 1
            else:
                self.content_type = 0
        if self.content_type == 1:
            self.content_de = cleaner.clean_html(self.content_de)
            self.content_en = cleaner.clean_html(self.content_en)
        elif self.content_type == 2 and not self.pdf_de.name:
            raise ValidationError(
                _(u'Please upload a PDF-File to this PDF-Page.'))

    def get_absolute_url(self):
        aboslute_url = '/' + self.path
        if self.content_type == 1:
            aboslute_url += '.html'
        elif self.content_type == 2:
            aboslute_url += '.pdf'
        else:
            aboslute_url += '/'
        return aboslute_url

    class Meta(object):
        ordering = ['parent__id', 'position']
        unique_together = (('slug', 'parent'),)
        verbose_name = _('Page')
        verbose_name_plural = _('Pages')


class Category(ImageModel):
    name_de = models.CharField(_('Name'), max_length=80)
    name_en = models.CharField(_('Name'), max_length=80, blank=True)
    description_de = models.TextField(_('Description'))
    description_en = models.TextField(_('Description'), blank=True)
    image = models.ImageField(_('Image'), upload_to='news/categories/',
                              blank=True, null=True)
    slug = models.SlugField(_('Slug'), unique=True, db_index=True)

    class Meta(object):
        ordering = ('slug',)
        verbose_name = _('Category')
        verbose_name_plural = _('Categories')

    @property
    def name(self):
        return getattr(self, "name_%s" % get_language(), self.name_de)

    @property
    def description(self):
        return getattr(self, "description_%s" % get_language(),
                       self.description_de)

    def get_absolute_url(self):
        return reverse('article-archive', kwargs={'category': self.slug})

    def __unicode__(self):
        return self.name


def force_cache_update(sender, instance, **kwargs):
    for page in instance.subpages.all():
        page.clean()
        page.save()
    cache.delete('all_pages')
    cache.delete('top_level_pages')


models.signals.post_delete.connect(force_cache_update, sender=Page)
models.signals.post_save.connect(force_cache_update, sender=Page)
