import java.awt.*;
import java.util.*;
import java.io.*;

class displayTree {

    public final static int kVertSpace = 40;
    public final static int kHorizSpace = 20;

    private Vector nodes = new Vector();
    private int rootPos;
    private int margin[] = new int[1024];
    private InputStream inStream;
    private int fileEOF = 0;
    private String msg = new String();

    public displayTree(InputStream in)  {
	
	inStream = in;
	//the first call to read stream will return a null rep
	readStream();
	//get the real rep here
	readStream();
    }
    
    public void readStream() {
	byte cur[] = new byte[2048];
	int i = 0, done = 0;
	Vector tmpNodes = new Vector();

	if (fileEOF == 1) return;
	
	do {
	    try {
		done = inStream.read(cur, i, 1);
		if (done == -1) fileEOF = 1;
	    } catch (IOException e) {
		System.err.println("IO exception");
		System.exit(0);
	    }

	    if (cur[i] == '\n') {
		String strRep = new String(cur, 0, i);
		if (strRep.startsWith("START")) {
		    done = -1;
		    msg = new String(strRep);
		} else {
		    displayNode newNode = new displayNode(strRep);
		    tmpNodes.addElement(newNode);
		    if (newNode.nodeID() == 1) rootPos = tmpNodes.size() - 1;
		    i = 0;
		}
	    } else {
		i++;
	    }
	} while (done != -1);
	if (fileEOF != 1) nodes = tmpNodes;
	System.err.println("Parsing complete");
    }

    public void drawSelf(Graphics g) {
	for (int i = 0; i < 1024; i++) margin[i] = 0;
	if (nodes.size() == 0) return;
	g.drawString(msg, 20, 400);
	displayNode root = (displayNode)nodes.elementAt(rootPos);
	drawNode(g, root, 1);
    }
    
    private void drawNode(Graphics g, displayNode n, int depth) {
	n.drawSelf(margin[depth], depth*kVertSpace, g);
	margin[depth] += n.totalWidth() + kHorizSpace;
	if (n.nodeType() == displayNode.kIndex) {
	    for (int i = 0; i < n.size(); i++) {
		Integer I = new Integer(n.dataAt(i));
		if (I.intValue() > 0) {
		    displayNode child = findNodeByID(I.intValue());
		    if (child.isVisible()) {
			g.setColor(new Color(0,0,0));
			g.drawLine(margin[depth] + n.width(i) - n.totalWidth() - kHorizSpace, 
				   depth*kVertSpace,margin[depth + 1], depth*kVertSpace + kVertSpace); 
			drawNode(g, child, depth + 1);
		    }
		}
	    }
	}
    }

    private displayNode findNodeByID(int i) {
	Enumeration e = nodes.elements();
	while (e.hasMoreElements() ) {
	    displayNode cand = (displayNode)e.nextElement();
	    if (cand.nodeID() == i) return cand;
	}
	return null;
    }

    public void setNodeVisibility(int nodeID, boolean vis) {
	if (nodeID == -1) {
	    Enumeration e = nodes.elements();
	    while (e.hasMoreElements() ) {
		displayNode cand = (displayNode)e.nextElement();
		cand.setVisible(vis);
	    }
	} else {
	    displayNode n = findNodeByID(nodeID);
	    n.setVisible(vis);
	}
    }
}





