import java.awt.*;
import java.util.Vector;

public class BSPCell
{
	public Face face;
	public Segment segment;
	public BSPCell parent;
	public BSPCell front;
	public BSPCell back;
	
	public BSPCell() {
		face = new Face(0, 0, Parameters.WIDTH, Parameters.HEIGHT);
		segment = null;
		parent = null;
		front = null;
		back = null;
	}
	
	public BSPCell(Face face) {
		this.face = face;
		segment = null;
		parent = null;
		front = null;
		back = null;
	}
	
	public void draw(Graphics g) {
		face.draw(g);
		if (front != null)
			front.draw(g);
		if (back != null)
			back.draw(g);	
	}
	
	public void fill(Graphics g) {
		face.fill(g);
	}
	
	public void insert(Segment s) {
		s = face.clip(s);
		if (s == null) return;
		if (front != null) 
			front.insert(s);
		if (back != null) 
			back.insert(s);
		if (segment == null)
			this.split(s);
	}
	
	public BSPCell locate(Vertex eye) {
		if (this.segment == null)
			return this;
		int e = segment.h.eval(eye);
		if (e == Parameters.COINCIDENT)
			return front.locate(eye);
		else if (e == Parameters.IN_FRONT)
			return front.locate(eye);
		else
			return back.locate(eye);
	}
	
	public Vector traverse(Vertex eye) {
		Vector ordered_segments = new Vector();
		traverse(eye, ordered_segments);
		return ordered_segments;
	}
	
	private void split(Segment s) {
		segment = s;
		Face [] faces = face.split(s);
		// create the front child
		if (faces[0] != null) {
			front = new BSPCell(faces[0]);
			front.parent = this;
		}
		// create the back child
		if (faces[1] != null) {
			back = new BSPCell(faces[1]);
			back.parent = this;
		}
	}
	
	private void traverse(Vertex eye, Vector segments) {
		if (this.segment == null)
			return;
		int e = this.segment.h.eval(eye);
		if (e == Parameters.IN_FRONT) {
			this.back.traverse(eye, segments);
			segments.addElement(this.segment);
			this.front.traverse(eye, segments);
		}
		else if (e == Parameters.IN_BACK) {
			this.front.traverse(eye, segments);
			segments.addElement(this.segment);
			this.back.traverse(eye, segments);
		}
		else {
			this.front.traverse(eye, segments);
			this.back.traverse(eye, segments);
		}
	}
}