""" Feed.py

Provides a module for managing feeds
"""
__copyright__ = "Copyright (c) 2002-2005 Free Software Foundation, Inc."
__license__ = """
Straw is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

Straw is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA. """


import Event
import FeedItems
import FeedDataRouter
import Config
from error import log

class Feed(object, Event.SignalEmitter):
    "A Feed object stores information set by user about a RSS feed."

    DEFAULT = -1
    STATUS_IDLE = 0
    STATUS_POLLING = 1

    __slots__ = ('_title', '_location', '_username', '_password', '_parsed',
                 '__save_fields', '_items', '_slots',
                 '_id', '_channel_description',
                 '_channel_title', '_channel_link', '_channel_copyright',
                 'channel_lbd', 'channel_editor', 'channel_webmaster',
                 'channel_creator', '_previous_etag',
                 '_error', '_process_status', 'router', 'sticky', '_parent',
                 '_items_stored', '_poll_freq', '_last_poll', '_n_items_unrea')

    __save_fields = (('_title', ""), ('_location', ""), ('_username', ""),
                     ('_password', ""), ('_id', ""),
                     ('_channel_description', ""), ('_channel_title', ""),
                     ('_channel_link', ""), ('_channel_copyright', ""),
                     ('channel_creator', ""),
                     ('_previous_etag', ""), ('_error', None),
                     ('_items_stored', DEFAULT),
                     ('_poll_freq', DEFAULT),
                     ('_last_poll', 0),
                     ('_n_items_unread', 0))


    # use one of the factory functions below instead of this directly
    def __init__(self, title="", location="", username="", password=""):
        Event.SignalEmitter.__init__(self)
        self.initialize_slots(Event.FeedInfoUpdatedSignal,
                              #Event.FeedUnreadChangedSignal,
                              #Event.FeedNumOfItemsStoredChangedSignal,
                              #Event.FeedPollFrequencyChangedSignal,
                              Event.FeedLastPollChangedSignal,
                              Event.FeedStatusChangedSignal,
                              Event.FeedErrorStatusChangedSignal,
                              Event.FeedPolledSignal,
                              Event.NewItemsSignal,
                              Event.ItemsAddedSignal,
                              Event.ItemReadSignal,
                              Event.ItemStickySignal,
                              Event.ItemDeletedSignal,
                              Event.AllItemsReadSignal,
                              Event.RefreshFeedDisplaySignal)

        self._title = title
        self._channel_description = ""
        self._channel_title = ""
        self._channel_link = ""
        self._channel_copyright = ""
        self.channel_lbd = None
        self.channel_editor = ""
        self.channel_webmaster = ""
        self.channel_creator = ""
        self._location = location
        self._username = username
        self._password = password
        self._parsed = None
        self._items = FeedItems.FeedItems(self)
        self._previous_etag = None
        self._error = None
        self._process_status = self.STATUS_IDLE
        self.router = FeedDataRouter.FeedDataRouter(self)
        self._parent = None
        self._items_stored = Feed.DEFAULT
        self._poll_freq = Feed.DEFAULT
        self._last_poll = 0
        self._n_items_unread = 0
        return

    def __str__(self):
        return "Feed '%s' from %s" % (self._title, self._location)

    @property
    def id(self):
        return self._id

    @apply
    def parsed():
        doc = "A ParsedSummary object generated from the summary file"
        def fget(self):
            return self._parsed
        def fset(self, parsed):
            self._parsed = parsed
        return property(**locals())

    @apply
    def title():
        doc = "The title of this Feed (as defined by user)"
        def fget(self):
            text = ''
            if self._title:
                text = self._title
            return text
        def fset(self, title):
            if self._title != title:
                self._title = title
                self.emit_signal(Event.FeedInfoUpdatedSignal(self))
        return property(**locals())

    @apply
    def access_info():
        doc = "A tuple of location, username, password"
        def fget(self):
            return (self._location, self._username, self._password)
        def fset(self, (location,username,password)):
            self._location = location
            self._username = username
            self._password = password
            self.emit_signal(Event.FeedInfoUpdatedSignal(self))
        return property(**locals())

    @apply
    def location():
        doc = ""
        def fget(self):
            return self._location
        def fset(self, location):
            if self._location != location:
                self._location = location
                self.emit_signal(Event.FeedInfoUpdateSignal(self))
        return property(**locals())

    @apply
    def channel_title():
        doc = ""
        def fget(self):
            text = ''
            if self._channel_title:
                text = self._channel_title
            return text
        def fset(self, t):
            changed = self._channel_title != t
            self._channel_title = t
            if changed:
                self.emit_signal(Event.FeedInfoUpdatedSignal(self))
        return property(**locals())

    @apply
    def channel_description():
        doc = ""
        def fget(self):
            text = ''
            if self._channel_description:
                text = self._channel_description
            return text
        def fset(self, t):
            changed = self._channel_description != t
            self._channel_description = t
            if changed:
                self.emit_signal(Event.FeedInfoUpdatedSignal(self))
        return property(**locals())

    @apply
    def channel_link():
        doc = ""
        def fget(self):
            return self._channel_link
        def fset(self, t):
            changed = self._channel_link != t
            self._channel_link = t
            if changed:
                self.emit_signal(Event.FeedInfoUpdatedSignal(self))
        return property(**locals())

    @apply
    def channel_copyright():
        doc = ""
        def fget(self):
            return self._channel_copyright
        def fset(self, t):
            changed = self._channel_copyright != t
            self._channel_copyright = t
            if changed:
                self.emit_signal(Event.FeedInfoUpdatedSignal(self))
        return property(**locals())

    @apply
    def number_of_items_stored():
        doc = ""
        def fget(self):
            return self._items_stored
        def fset(self, num=None):
            if self._items_stored != num:
                self._items_stored = num
                self.emit_signal(Event.FeedNumOfItemsStoredChangedSignal(self))
        return property(**locals())

    @apply
    def poll_frequency():
        doc = ""
        def fget(self):
            return self._poll_freq
        def fset(self, freq):
            if self._poll_freq != freq:
                self._poll_freq = freq
                self.emit_signal(Event.FeedPollFrequencyChangedSignal(self))
        return property(**locals())

    @apply
    def last_poll():
        doc = ""
        def fget(self):
            return self._last_poll
        def fset(self, time):
            if self._last_poll != time:
                self._last_poll = time
                self.emit_signal(Event.FeedLastPollChangedSignal(self))
        return property(**locals())

    @apply
    def n_items_unread():
        doc = ""
        def fget(self):
            return self._n_items_unread
        def fset(self, n):
            if self._n_items_unread != n:
                self._n_items_unread = n
                self.emit_signal(Event.FeedUnreadChangedSignal(self))
        return property(**locals())

    @apply
    def previous_etag():
        doc = ""
        def fget(self):
            return self._previous_etag
        def fset(self, etag):
            self._previous_etag = etag
        return property(**locals())

    @apply
    def error():
        doc = ""
        def fget(self):
            return self._error
        def fset(self, error):
            if self._error != error:
                self._error = error
                self.emit_signal(Event.FeedErrorStatusChangedSignal(self))
        return property(**locals())

    @apply
    def process_status():
        doc = ""
        def fget(self):
            return self._process_status
        def fset(self, status):
            if status != self._process_status:
                self._process_status = status
                self.emit_signal(Event.FeedStatusChangedSignal(self))
        return property(**locals())

    @apply
    def parent():
        doc = ""
        def fget(self):
            return self._parent
        def fset(self, parent):
            self._parent = parent
        return property(**locals())

    @property
    def next_refresh(self):
        """ return the feed's next refresh (time)"""
        nr = None
        if self._poll_freq == self.DEFAULT:
            increment = Config.get_instance().poll_frequency
        else:
            increment = self._poll_freq
        if increment > 0:
            nr = self.last_poll + increment
        return nr

    def dump(self):
        fl = {}
        for f, default in self.__save_fields:
            fl[f] = self.__getattribute__(f)
        return fl

    def undump(self, dict):
        for f, default in self.__save_fields:
            self.__setattr__(f, dict.get(f, default))
        return

    def poll_done(self):
        self.emit_signal(Event.FeedPolledSignal(self))

    def signal_new_items(self, items):
        self.emit_signal(Event.NewItemsSignal(self, items))

    def signal_added_items(self, items):
        self.emit_signal(Event.ItemsAddedSignal(self, items))

    def signal_deleted_item(self, item):
        self.emit_signal(Event.ItemDeletedSignal(self, item))

    def signal_refresh_display(self):
        self.emit_signal(Event.RefreshFeedDisplaySignal(self))

    def signal_all_items_read(self, items):
        self.emit_signal(Event.AllItemsReadSignal(self, items))

    def forward_signal(self, signal):
        self.emit_signal(signal)

    def add_items(self, items):
        return self._items.add_items(items)

    def restore_items(self, items):
        return self._items.restore_items(items)

    def delete_all_items(self):
        self.signal_deleted_item(self.items)

    def get_item_index(self, item):
        return self._items.get_item_index(item)

    @property
    def items(self):
        return self._items.get_items()

    @property
    def number_of_unread(self):
        return self._n_items_unread

    @property
    def number_of_items(self):
        return self._items.number_of_items

    def mark_all_read(self):
        return self._items.mark_all_read()

    def load_contents(self):
        return self._items.load()

    def unload_contents(self):
        self._items.unload()

    @classmethod
    def create_new_feed(klass, title, location="", username="", password=""):
        f = klass()
        f._title = title
        f._location = location
        f._id = Config.get_instance().next_feed_id_seq()
        f._username = username
        f._password = password
        return f

    @classmethod
    def create_empty_feed(klass):
        f = klass()
        return f
