from django.core.exceptions import ValidationError
from django.db import models
from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _

from feincms_oembed.models import CachedLookup


class OembedContent(models.Model):
    """
    Content type for integrating anything supported by the oembed provider into
    the CMS

    Usage::

        Page.create_content_type(OembedContent, TYPE_CHOICES=[
            ('default', _('Default presentation'), {
                'maxwidth': 500, 'maxheight': 300}),
            ('transparent', _('Transparent'), {
                'maxwidth': 500, 'maxheight': 300, 'wmode': 'transparent'}),
            ])
    """

    url = models.URLField(
        _("URL"),
        help_text=_(
            "Insert an URL to an external content you want to embed,"
            " e.g. http://www.youtube.com/watch?v=Nd-vBFJN_2E"
        ),
    )

    class Meta:
        abstract = True
        verbose_name = _("external content")
        verbose_name_plural = _("external contents")

    @classmethod
    def initialize_type(cls, TYPE_CHOICES, PARAMS={}):
        choices = [row[0:2] for row in TYPE_CHOICES]
        cls.add_to_class(
            "type",
            models.CharField(
                _("type"), max_length=20, choices=choices, default=choices[0][0],
            ),
        )
        cls._type_config = dict((row[0], row[2]) for row in TYPE_CHOICES)
        cls._params = PARAMS

    def get_html_from_json(self, fail_silently=False):
        params = self._type_config.get(self.type, {})
        params.update(self._params)

        try:
            embed = CachedLookup.objects.oembed(self.url, **params)
        except TypeError:
            if fail_silently:
                return u""
            raise ValidationError(_("I don't know how to embed %s.") % self.url)

        return render_to_string(
            (
                "content/external/%s.html" % embed.get("type"),
                "content/external/%s.html" % self.type,
                "content/external/default.html",
            ),
            {"response": embed, "content": self},
        )

    def clean(self, *args, **kwargs):
        self.get_html_from_json()

    def render(self, **kwargs):
        return self.get_html_from_json(fail_silently=True)


class FeedContent(models.Model):
    url = models.URLField(
        _("Feed URL"),
        help_text=_(
            "Insert any RSS URL," " e.g. https://www.djangoproject.com/rss/weblog/"
        ),
    )

    class Meta:
        abstract = True
        verbose_name = _("RSS Feed")
        verbose_name_plural = _("RSS Feeds")

    def clean(self, *args, **kwargs):
        import feedparser

        feedparser.parse(CachedLookup.objects.request(self.url, 30 * 60))

    @property
    def feed(self):
        import feedparser

        return feedparser.parse(CachedLookup.objects.request(self.url, 30 * 60))

    def render(self, **kwargs):
        return "content/external/feed.html", {"feed": self.feed}


class OembedMixin(models.Model):
    """
    Mixin for usage in custom feincms content types
    Usage::

        Page.create_content_type(
            YourContentWithOembedMixin,
            OEMBED_PARAMS={
                'maxwidth': 500,
                'maxheight': 300,
                'wmode': 'transparent',
            },
        )

    Oembed content will be available via self.oembed
    """

    url = models.URLField(
        _("Video URL"),
        help_text=_(
            "Insert an URL to an external content you want to embed,"
            " e.g. http://www.youtube.com/watch?v=Nd-vBFJN_2E"
        ),
        blank=True,
    )

    class Meta:
        abstract = True

    @classmethod
    def initialize_type(cls, OEMBED_PARAMS={}):
        cls._params = OEMBED_PARAMS

    def get_html_from_json(self, fail_silently=False):
        if not self.url:
            self.oembed = ""
            return True

        params = {}
        params.update(self._params)

        try:
            embed = CachedLookup.objects.oembed(self.url, **params)
        except TypeError:
            if fail_silently:
                return u""
            raise ValidationError(_("I don't know how to embed %s.") % self.url)

        self.oembed = embed

    def process(self, request, **kwargs):
        self.get_html_from_json()
