"""
$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/dulcinea/lib/property/property_list.py $
$Id: property_list.py 29610 2007-03-14 21:12:59Z dbinger $
"""
from dulcinea.base import DulcineaPersistent
from dulcinea.property.property import Property
from dulcinea.property.property_template import PropertyTemplate
from qp.lib.spec import either, require


class PropertyList (DulcineaPersistent):

    list_is = [either(Property, PropertyTemplate)]

    def __init__(self, values=None):
        self.list = []
        if values:
            for value in values:
                self.add(value)

    def __copy__(self):
        result = self.__class__()
        result.list = self.list[:]
        return result

    def __eq__(self, other):
        require(other, PropertyList)
        if len(self) != len(other):
            return False
        def as_dict(property_list):
            return dict((p.get_name(), p) for p in property_list)
        return as_dict(self) == as_dict(other)

    def __str__(self):
        return "PropertyList(%s)" % self.list

    def __len__(self):
        return len(self.list)

    def __getitem__(self, index):
        return self.list[index]

    def __add__(self, other):
        newlist = PropertyList()
        if isinstance(other, PropertyList):
            newlist.list = self.list + other.list
        else:
            newlist.list = self.list[:]
            for item in other:
                newlist.add(item)
        return newlist

    def get_names(self):
        """() -> [string]

        Return the list of all names in the list.
        """
        return [property.get_name() for property in self]

    def find(self, name):
        """(name : string) -> any

        Searches the list for a value with name 'name'.  Returns the
        matching value, or None if it couldn't find one.
        """
        for property in self.list:
            if name == property.get_name():
                return property
        require(name, basestring)
        return None

    def add(self, property):
        """(property : Property|PropertyTemplate)

        Raises ValueError if this list already has a value with the same name.
        """
        require(property, either(Property, PropertyTemplate))
        if self.find(property.get_name()) is not None:
            raise ValueError, \
                  "list already has a value named %r" % property.get_name()
        self._p_note_change()
        self.list.append(property)

    def remove(self, name):
        """(name : string)

        Find the value named by 'name' and remove it.
        """
        require(name, basestring)
        for index, property in enumerate(self):
            if name == property.get_name():
                self._p_note_change()
                del self.list[index]

    def __iter__(self):
        for item in self.list:
            yield item

    def _get_instances(self, klass):
        return [p for p in self.list if isinstance(p, klass)]

    def get_value_properties(self):
        """Return a new PropertyList containing all properties from the
        current list that have values.
        """
        result = PropertyList()
        result.list = self._get_instances(Property)
        return result

    def get_templates(self):
        """Return a new PropertyList containing all properties from the
        current list that don't have values.
        """
        result = PropertyList()
        result.list = self._get_instances(PropertyTemplate)
        return result

    def get_visible(self):
        result = PropertyList()
        result.list = [property for property in self
                       if not property.is_hidden()]
        return result
