import urllib

from haystack.query import SearchQuerySet

from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Rss201rev2Feed
from django.core.urlresolvers import reverse, reverse_lazy
from django.conf import settings

from .models import Person, Bill, Organization, Event


class CouncilmaticFacetedSearchFeed(Feed):
    title_template = 'feeds/search_item_title.html'
    description_template = 'feeds/search_item_description.html'
    bill_model = Bill

    all_results = None
    sqs = SearchQuerySet().facet('bill_type')\
                          .facet('sponsorships', sort='index')\
                          .facet('controlling_body')\
                          .facet('inferred_status')
    query = None

    def url_with_querystring(self, path, **kwargs):
        return path + '?' + urllib.parse.urlencode(kwargs)

    def get_object(self, request):
        self.queryDict = request.GET
        all_results = SearchQuerySet().all()
        facets = None

        if 'selected_facets' in request.GET:
            facets = request.GET.getlist('selected_facets')

        if 'q' in request.GET:
            self.query = request.GET['q']
            results = all_results.filter(content=self.query)

            if facets:
                for facet in facets:
                    (facet_name, facet_value) = facet.split(':')
                    facet_name = facet_name.rsplit('_exact')[0]
                    results = results.narrow('%s:%s' % (facet_name, facet_value))
        elif facets:
            for facet in facets:
                (facet_name, facet_value) = facet.split(':')
                facet_name = facet_name.rsplit('_exact')[0]
                results = all_results.narrow('%s:%s' % (facet_name, facet_value))

        return results.order_by('-last_action_date')

    def title(self, obj):
        if self.query:
            title = settings.SITE_META['site_name'] + ": Search for '" + self.query.capitalize() + "'"
            # XXX: create a nice title based on all search parameters
        else:
            title = settings.SITE_META['site_name'] + ": Filtered Search"

        return title

    def link(self, obj):
        # return the main non-RSS search URL somehow
        # XXX maybe "quargs" - evz
        # return reverse('councilmatic_search', args=(searchqueryset=self.sqs,))
        url = self.url_with_querystring(reverse('{}:councilmatic_search_feed'.format(settings.APP_NAME)), q=self.query)
        return url

    def item_link(self, bill):
        return reverse('bill_detail', args=(bill.slug,))

    def item_pubdate(self, bill):
        return bill.last_action_date

    def description(self, obj):
        return "Bills returned from search"

    def items(self, searchresults):
        l_items = list(searchresults)[:20]
        # turn these into bills. XXX: should override in subclasses, e.g. NYCCouncilmaticFacetedSearchFeed,
        # to access methods like inferred_status()
        pks = [i.pk for i in l_items]
        bills = self.bill_model.objects.filter(pk__in=pks).order_by('-last_action_date')
        return list(bills)


class PersonDetailFeed(Feed):
    """The PersonDetailFeed provides an RSS feed for a given committee member,
    returning the most recent 20 bills for which they are the primary sponsor;
    and for each bill, the list of sponsores and the action history.
    """

    title_template = 'feeds/person_detail_item_title.html'
    description_template = 'feeds/person_detail_item_description.html'
    feed_type = Rss201rev2Feed
    NUM_RECENT_BILLS = 20

    def get_object(self, request, slug):
        o = Person.objects.get(slug=slug)
        return o

    def title(self, obj):
        return settings.SITE_META['site_name'] + ': ' + settings.CITY_VOCAB['COUNCIL_MEMBER'] + " %s: Recently Sponsored Bills" % obj.name

    def link(self, obj):
        # return the Councilmatic URL for the person
        # XXX maybe put this in models.py:Person.get_absolute_url() instead (https://docs.djangoproject.com/en/1.9/ref/models/instances/ , https://docs.djangoproject.com/en/1.9/ref/contrib/syndication/)
        return reverse('person', args=(obj.slug,))

    # Return sponsored legislation a la https://nyc.councilmatic.org/person/margaret-s-chin/
    def item_link(self, bill):
        # return the Councilmatic URL for the bill
        return reverse('bill_detail', args=(bill.slug,))

    def item_pubdate(self, bill):
        return bill.last_action_date

    def description(self, obj):
        return "Recent sponsored bills from " + obj.name + "."

    def items(self, person):
        sponsored_bills = [s.bill for s in person.primary_sponsorships.order_by('-_bill__last_action_date')[:10]]
        recent_sponsored_bills = sponsored_bills[:self.NUM_RECENT_BILLS]
        return recent_sponsored_bills


class CommitteeDetailEventsFeed(Feed):
    """The CommitteeDetailEventsFeed provides an RSS feed for a given committee,
    returning the most recent 20 events.
    """

    title_template = 'feeds/committee_events_item_title.html'
    description_template = 'feeds/committee_events_item_description.html'
    feed_type = Rss201rev2Feed
    NUM_RECENT_COMMITTEE_EVENTS = 20

    def get_object(self, request, slug):
        o = Organization.objects.get(slug=slug)
        return o

    def title(self, obj):
        return settings.SITE_META['site_name'] + ": " + obj.name + ": Recent Events"

    def link(self, obj):
        # return the Councilmatic URL for the committee
        return reverse('committee_detail', args=(obj.slug,))

    def item_link(self, event):
        # return the Councilmatic URL for the event
        return reverse('event_detail', args=(event.slug,))

    def item_pubdate(self, event):
        return event.start_time

    def description(self, obj):
        return "Events for committee %s" % obj.name

    def items(self, obj):
        events = obj.recent_events.all()[:self.NUM_RECENT_COMMITTEE_EVENTS]
        levents = list(events)
        return levents


class CommitteeDetailActionFeed(Feed):
    """The CommitteeDetailActionFeed provides an RSS feed for a given committee,
    returning the most recent 20 actions on legislation.
    """

    # instead of defining item_title() or item_description(), use templates
    title_template = 'feeds/committee_actions_item_title.html'
    description_template = 'feeds/committee_actions_item_description.html'
    feed_type = Rss201rev2Feed
    NUM_RECENT_COMMITTEE_ACTIONS = 20

    def get_object(self, request, slug):
        o = Organization.objects.get(slug=slug)
        return o

    def title(self, obj):
        return settings.SITE_META['site_name'] + ": " + obj.name + ": Recent Actions"

    def link(self, obj):
        # return the Councilmatic URL for the committee
        return reverse('committee_detail', args=(obj.slug,))

    def item_link(self, action):
        # return the Councilmatic URL for the bill
        return reverse('bill_detail', args=(action.bill.slug,))

    def item_pubdate(self, action):
        return action.date

    def description(self, obj):
        return "Actions for committee %s" % obj.name

    def items(self, obj):
        actions = obj.recent_activity[:self.NUM_RECENT_COMMITTEE_ACTIONS]
        actions_list = list(actions)
        return actions_list


class BillDetailActionFeed(Feed):
    """
    Return the last 20 actions for a given bill.
    """

    # instead of defining item_title() or item_description(), use templates
    title_template = 'feeds/bill_actions_item_title.html'
    description_template = 'feeds/bill_actions_item_description.html'
    feed_type = Rss201rev2Feed
    NUM_RECENT_BILL_ACTIONS = 20

    def get_object(self, request, slug):
        o = Bill.objects.get(slug=slug)
        return o

    def title(self, obj):
        return settings.SITE_META['site_name'] + ": " + obj.friendly_name + ": Recent Actions"

    def link(self, obj):
        # return the Councilmatic URL for the committee
        return reverse('bill_detail', args=(obj.slug,))

    def item_link(self, action):
        # Bill actions don't have their own pages, so just link to the Bill page (?)
        return reverse('bill_detail', args=(action.bill.slug,))

    def item_pubdate(self, action):
        return action.date

    def description(self, obj):
        return "Actions for bill %s" % obj.friendly_name

    def items(self, obj):
        actions = obj.ordered_actions[:self.NUM_RECENT_BILL_ACTIONS]
        actions_list = list(actions)
        return actions_list


class EventsFeed(Feed):
    """
    Return the last 20 announced events as per, e.g., https://nyc.councilmatic.org/events/
    """
    title_template = 'feeds/events_item_title.html'
    description_template = 'feeds/events_item_description.html'
    feed_type = Rss201rev2Feed
    NUM_RECENT_EVENTS = 20

    title = settings.CITY_COUNCIL_NAME + " " + "Recent Events"
    link = reverse_lazy('events')
    description = "Recently announced events."

    def item_link(self, event):
        # return the Councilmatic URL for the event
        return reverse('event_detail', args=(event.slug,))

    def item_pubdate(self, event):
        return event.start_time

    def description(self, obj):
        return "Events"

    def items(self, obj):
        events = Event.objects.all()[:self.NUM_RECENT_EVENTS]
        levents = list(events)
        return levents
