from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
from django.utils import feedgenerator
from django.contrib.sites.models import Site
from pycon.core import safe_ascii_encode
from permissions import UserPermissions
from changelog import full_change_history

def extend_change(change, user, proposal=None):
    """The default change does not contain all the information teh feed needs
    This call extends the changeinfo by adding the missing attributes"""
    if not hasattr(change, 'model'):
        change.model = change.content_type.model
    try:
        if not hasattr(change, 'proposal'):
            if proposal is not None:
                change.proposal = proposal
            else:
                mod = change.model
                if change.model == 'proposal':
                    change.proposal = change.get_edited_object()
                else:
                    change.proposal = change.get_edited_object().proposal
        change.can_view_details = UserPermissions.history_change_can_be_viewed(
            change, (change.proposal, user))
        change.author_name = change.user.protected_proposal_user_name(
            (change.proposal, user))
    except:
        change.can_view_details = False
        change.proposal = 'Unknown'
        try:
            change.author_name = 'User #%d' % change.user.id
        except:
            change.author_name = 'Unknwon'
    return change

class ProposalChangeHistoryFeed(Feed):
    def __init__(self, slug, request, query=None, proposal=None, url=None,
                 title=None, description=None, limit=-1):
        super(ProposalChangeHistoryFeed, self).__init__(slug, request)
        self.proposal = proposal
        if url is not None: self.feed_url = url
        self.site_name = safe_ascii_encode(Site.objects.get_current().name)
        if title is not None:
            self.title = title
        if description is not None:
            self.description = description
        self.query = query
        self.user = request.user
        self.limit = limit
    def title(self, obj):
        """
        Returns the feed's title as a normal Python string.
        """
        return ('Recent Changes to ' + str(obj.id) + '. ' +
                safe_ascii_encode(unicode(obj)))
    def description(self, obj):
        """
        Returns the feed's description as a normal Python string.
        """
        return ('Recent changes to ' + self.site_name + ' Talk Proposal: ' +
                str(obj.id) + '. ' + safe_ascii_encode(unicode(obj)))
    def link(self):
        """
        Returns the feed's link as a normal Python string.
        """
        return safe_ascii_encode(self.request.path)
    def get_object(self, bits):
        """
        Takes a list of strings gleaned from the URL and returns an object
        represented by this feed. Raises
        django.core.exceptions.ObjectDoesNotExist on error.
        """
        return self.query if self.query is not None else self.proposal
    def items(self):
        """
        Takes the object returned by get_object() and returns a list of
        items to publish in this feed.
        """
        change_history = self.query
        if self.query is None:
            change_history = full_change_history(self.proposal, False)

        if not (self.limit < 1 or self.limit >= change_history.count()):
            change_history = change_history[:self.limit]
        return (extend_change(change, self.user, self.proposal)
                for change in change_history)
    def item_link(self, item):
        """
        Takes an item, as returned by items(), and returns the item's URL.
        """
        return item.proposal.get_absolute_url()
    def item_guid(self, item):
        """
        Takes an item, as return by items(), and returns the item's ID.
        """
        return self.slug + str(item.id)
    def item_author_name(self, item):
        """
        Takes an item, as returned by items(), and returns the item's
        author's name as a normal Python string.
        """
        return item.author_name
    def item_pubdate(self, item):
        """
        Takes an item, as returned by items(), and returns the item's
        pubdate.
        """
        return item.action_time
