class MultipleValuesIndex(Index):
    """An `index <Index>` where keys may be defined multiple times."""

    accepts_multiple_values = True

    @overrides(Index.__init__)
    def __init__(self, pairs = None):
        self.__items = OOTreeSet()
        self.__descending_items = OOTreeSet()
        Index.__init__(self, pairs)

    @overrides(Index.add)
    def add(self, key, value):
        self.__items.insert(Entry(key, value))
        self.__descending_items.insert(DescEntry(key, value))

    @overrides(Index.remove)
    def remove(self, key, value = undefined):

        entry = Entry(key, value)
        desc_entry = DescEntry(key, value)

        # Remove all values for the given key
        if value is undefined:
            while True:
                try:
                    self.__items.remove(entry)
                    self.__descending_items.remove(desc_entry)
                except KeyError:
                    break
        # Remove a specific value for the given key
        else:
            try:
                self.__items.remove(entry)
                self.__descending_items.remove(desc_entry)
            except KeyError:
                pass

    @overrides(Index.items)
    def items(
        self,
        min = undefined,
        max = undefined,
        exclude_min = False,
        exclude_max = False,
        descending = False
    ):
        if descending:
            return self.__descending_items.keys(
                min = None if max is undefined
                      else DescEntry(
                          max,
                          lower_bound if exclude_max else upper_bound
                      ),
                max = None if min is undefined
                      else DescEntry(
                          min,
                          upper_bound if exclude_min else lower_bound
                      )
            )
        else:
            return self.__items.keys(
                min = None if min is undefined
                      else Entry(
                          min,
                          upper_bound if exclude_min else lower_bound
                      ),
                max = None if max is undefined
                      else Entry(
                          max,
                          lower_bound if exclude_max else upper_bound
                      )
            )

    @overrides(Index.min_key)
    def min_key(self, exclude_none = False):
        if exclude_none:
            for key in self.keys(min = None, include_min = False):
                return key
        else:
            return self.__items.minKey().key

    @overrides(Index.max_key)
    def max_key(self):
        return self.__items.maxKey().key

    @overrides(Index.__len__)
    def __len__(self):
        return len(self.__items)

    @overrides(Index.__bool__)
    def __bool__(self):
        return bool(self.__items)

    @overrides(Index.__contains__)
    def __contains__(self, key):
        for value in self.values(key = key):
            return True

        return False