############################################################################
#
# File Name: 		ListBase.py
#
# Documentation:	http://docs.ftsuite.com/4ODS/List.py.html
#
"""
Lists: ordered collections.
WWW: http://4suite.org/4ODS         e-mail: support@4suite.org

Copyright (c) 1999 Fourthought, Inc., USA.   All Rights Reserved.
See  http://4suite.org/COPYRIGHT  for license and copyright information
"""

from Ft.Ods.StorageManager.Adapters import Constants
from Ft.Ods.Collections import CollectionBase
from Ft.Ods import Exception

class ListBase:

    _collectionType = Constants.CollectionTypes.LIST

    InvalidIndex = Exception.InvalidIndex

    def is_ordered(self):
        return 1

    def allows_duplicates(self):
        return 1

    def remove_element_at(self, index):
        if index < 0:
            raise ListBase.InvalidIndex(index)
        if index >= self.cardinality():
            raise ListBase.InvalidIndex(index)

        old = self._values[index]
        values = {}
        for i,v in self._values.items():
            if i >= index:
                i = i -1
            values[i] = v
        if values.has_key(-1):
            del values[-1]
        self._values = values

        self._4ods_addChange(Constants.CollectionChanges.REMOVE,index,old)


    def retrieve_element_at(self, index):
        if index < 0:
            raise ListBase.InvalidIndex(index)
        if index >= self.cardinality():
            raise ListBase.InvalidIndex(index)
        try:
            return self[index]
        except IndexError:
            raise ListBase.InvalidIndex(index)

    def replace_element_at(self, element, index):
        if index < 0:
            raise ListBase.InvalidIndex(index)
        if index >= self.cardinality():
            raise ListBase.InvalidIndex(index)

        self._4ods_addChange(Constants.CollectionChanges.REMOVE,index,self._values[index])
        el = self._4ods_unprepareValue(element)
        self._values[index] = el
        self._4ods_addChange(Constants.CollectionChanges.INSERT,index,el)


    def insert_element_after(self, element, index):
        if index < 0:
            raise ListBase.InvalidIndex(index)
        if index >= self.cardinality():
            raise ListBase.InvalidIndex(index)
            
        newIndex = index + 1
        for index,value in self._values.items():
            if index >= newIndex:
                self._values[index+1] = value
        el = self._4ods_unprepareValue(element)
        self._values[newIndex] = el
        self._4ods_addChange(Constants.CollectionChanges.INSERT,newIndex,el)
        return


    def insert_element_before(self, element, index):
        if index < 0:
            raise ListBase.InvalidIndex(index)
        if index >= self.cardinality():
            raise ListBase.InvalidIndex(index)

        newIndex = index
        for index,value in self._values.items():
            if index >= newIndex:
                self._values[index+1] = value
        el = self._4ods_unprepareValue(element)
        self._values[newIndex] = el
        self._4ods_addChange(Constants.CollectionChanges.INSERT,newIndex,el)
        return



    def insert_element_first(self, obj):
        for index,value in self._values.items():
            self._values[index+1] = value
        el = self._4ods_unprepareValue(obj)
        self._values[0] = el
        self._4ods_addChange(Constants.CollectionChanges.INSERT,0,el)
        return
    
    def insert_element_last(self, obj):
        self.append(obj)

    def remove_first_element(self):
        self.remove_element_at(0)

    def remove_last_element(self):
        self.remove_element_at(self.cardinality()-1)

    def retrieve_first_element(self):
        try:
            return self[0]
        except IndexError:
            raise CollectionBase.CollectionBase.ElementNotFound(None)

    def retrieve_last_element(self):
        try:
            return self[-1]
        except IndexError:
            raise CollectionBase.CollectionBase.ElementNotFound(None)

    def concat(self, otherList):
        result = self.copy(deep=0)
        result.append(self)
        result.append(otherList)
        return result

    def append(self, otherList):
        if not isinstance(otherList,ListBase):
            otherList = [otherList]

        for o in otherList:
            CollectionBase.CollectionBase.insert_element(self,o)

    insert_element = insert_element_last


    def _4ods_getOdsType(self):
        return Constants.Types.LIST_COLLECTION
