"""$URL: svn+ssh://svn/repos/trunk/dulcinea/lib/item.py $
$Id: item.py 26063 2005-02-11 14:39:59Z dbinger $
"""
from dulcinea.base import DulcineaPersistent
from dulcinea.spec import boolean
from dulcinea.timestamped import Timestamped, reverse_timestamp_sorted
from dulcinea.typeutils import typecheck
from dulcinea.util import datetime_to_int
from durus.persistent_dict import PersistentDict
from quixote import get_user

class Item(DulcineaPersistent, Timestamped):
    """An Item object implements a mixin API for a unique stored item
    retrievable by creation time.

    Instance attributes:
      title: string
        The title of this item
      key : string
        Some sort of unique ID
      approved : boolean
        Whether this item has been approved.
    """

    title_is = str
    key_is = str
    approved_is = boolean

    def __init__(self):
        assert self.__class__ is not Item, "abstract class"
        Timestamped.__init__(self)
        self.key = None
        self.title = None
        self.approved = False

    def __cmp__(self, other):
        typecheck(other, Item)
        return cmp(self.get_timestamp(), other.get_timestamp())

    def absorb(self, other):
        assert self.__class__ is other.__class__
        for attr_name in self.__dict__:
            if attr_name != 'key':
                self.__dict__[attr_name] = other.__dict__[attr_name]
        self._p_changed = 1

    def set_key(self, key):
        typecheck(key, str)
        assert self.key is None, "Item already has a key"
        self.key = key

    def get_key(self):
        return self.key

    def set_title(self, title):
        typecheck(title, str)
        self.title = title

    def get_title(self):
        return self.title

    def set_approved(self, approved):
        typecheck(approved, bool)
        self.approved = approved

    def is_approved(self):
        return self.approved

    def get_user(self):
        return None

    def changes_allowed(self):
        user = get_user()
        if not user:
            return False
        if not (user is self.get_user() or user.is_admin()):
            return False
        return True


class ItemFolder(DulcineaPersistent):
    """Stores a collection of Items and defines an API for storage
    and creation-time-based retrieval.

    Instance attributes:
      items : PersistentDict { string : Item }
    """

    def __init__(self):
        self.items = PersistentDict()

    def clear(self):
        self.items.clear()

    def add_item(self, item):
        """(item : Item)
        """
        typecheck(item, Item)
        i = 0
        while 1:
            key =  '%s-%s' % (datetime_to_int(item.get_timestamp()), i)
            if not self.items.has_key(key):
                break
            i += 1
        item.set_key(key)
        self.items[key] = item

    def delete_item(self, item):
        """(item : Item)
        """
        typecheck(item, Item)
        if item.get_key() is None:
            raise KeyError, "Item %r not in any database" % item
        if not self.items.has_key( item.key ):
            raise KeyError, "Item %r not in this database" % item
        del self.items[item.get_key()]

    def get_item(self, key):
        """(key : str) -> Item
        """
        return self.items[key]

    def get_items(self):
        """() -> [Item]
        """
        return self.items.values()

    def get_recent_items(self, count=None, include_unapproved=False):
        """(count : int = None, include_unapproved : bool = False) -> [Item]

        Return the 'count' most recent items.  If 'include_unapproved' is True,
        both un-approved and approved items are returned.
        The list returned is in reverse-chronological order by timestamp.
        """
        typecheck(count, int, allow_none=1)
        result = []
        for item in self.items.values():
            if item.is_approved() or include_unapproved:
                result.append(item)
        result = reverse_timestamp_sorted(result)
        if count is not None:
            result = result[:count]
        return result
