#!/usr/bin/env python

# Jacob Joseph
# 11 June 2008

class cobj(object):
    """A simple hierarchical cluster class"""
    def __init__(self, distance=None, cluster_id=None, left=None,
                 right=None, items=None, traversed=False):
        
        self.__distance = distance
        self.__cluster_id = cluster_id

        # Nested set indicies (Joe Celko)
        self.__left = left
        self.__right = right

        if items is None: self.__items = []
        else: self.__items = list(items)

        self.__traversed = traversed
        
    def __str__(self):
        s = "id: %s, dist: %s, L: %s, R: %s, #items: %d " % (
            self.__cluster_id, self.__distance, self.__left,
            self.__right, len(self.__items))
        return s

    def __repr__(self):
        return (self.__cluster_id, len(self.__items), self.__distance).__repr__()
        
    def items(self):
        return self.__items

    def add_child(self, item):
        self.__items.append(item)
        return
    
    def distance(self):
        return self.__distance

    def cluster_id(self):
        return self.__cluster_id
    
    def set_left(self, left):
        self.__left = left

    def left(self):
        return self.__left

    def set_right(self, right):
        self.__right = right
        
    def right(self):
        return self.__right

    def set_traversed(self, traversed=True):
        self.__traversed = traversed

    def traversed(self):
        return self.__traversed
    

    def print_hierarchy(self):
        """Print a hierarchical subtree"""

        s = ""
        s_cluster = "Cluster: %d -- Dist %g (L:%d, R:%d)"
        
        # stack of (level, cluster) tuples, where level is the amount
        # of indentation needed
        queue = []
        queue.append( (0, self))
        while len(queue) > 0:
            (level, clust) = queue.pop()

            if level < 100:
                s += level*" "
            else:
                s += " *%d* " % level
                
            s += s_cluster % (clust.cluster_id(),
                              clust.distance(),
                              0, 0)
            for child in clust.items():
                if isinstance(child, cobj):
                    queue.append( (level + 1, child))
                else:
                    s += " %s" % child

            s += "\n"
        return s


    def iter(self):

        queue = []
        queue.append( (0, self))
        while len(queue) > 0:
            (level, clust) = queue.pop()

            for child in clust.items():
                if isinstance(child, cobj):
                    queue.append( (level + 1, child))

            yield (level, clust)
