import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.URL;
import java.io.*;
import java.net.MalformedURLException;
import KioskControl;
import java.awt.image.*;

/**
 * KioskCanvas.java
 * The actual drawing plane for the Navigation Tree to draw.<p>
 *
 * The applet actually splits the canvas up into 2 parts, one for the<br>
 * left hand side of the applet, consisting of the markers, and the<br>
 * right side, consisting of the URL's and commands.<p>
 *
 * This can be seen why in the leftAction, rightAction, leftStatus and<br>
 * rightStatus methods below. 
 *
 * @version 1.0, August 1998
 * @author  Robert B. Weeks
 */

public class KioskCanvas extends Canvas {
	// Instance variables

	// Make a reference to the original applet.
	KioskControl parentApp	= null;
	
	// Font vars
	static int fontSize			= 12;
	
	// Size Variables
	static int appWidth;
	static int appHeight;
	
	// For new open/close markers
	static boolean createOpenImage	= false;
	static boolean createCloseImage	= false;
	static String closeImageName	= null;
	static String openImageName 	= null;
	static URL closeImageURL		= null;
	static URL openImageURL 		= null;
	static Image closeImage 		= null;
	static Image openImage 			= null;
	MediaTracker imageTrack 		= null;
	
	// For the colors
	static Color bgColor			= null;
	
	// For double-buffering thre tree for flicker-free display.
	Image bufferImage 			= null;
	Graphics bufferGraphics		= null;
	
	// For the tree itself
	Vector treeDisplay 			= new Vector();	
	
  
	/*
	 ****************************************************************
	 * Constructor.
	 ****************************************************************
	 */

	/**
	 * Sets up the KioskCanvas for drawing onto. The actual display<br>
	 * of the tree.. 
	 *
	 * @param	parent	The KioskControl applet.
	 * @param	width	The width of the applet.
	 * @param	height	The height of the applet.
	 */
	public KioskCanvas(KioskControl parent,int width, int height) {
		try {
			// The applet context - for reference to the applet itself
			parentApp = parent;
		
			// Resize to fill up the applet space
			setSize(width,height);
		
			// Set the height and width for later use
			appWidth = width;
			appHeight = height;
		
			// Counter for images (for the imageTrack)
			int imageCount = 0;
			
			// Add the mouse listeners (1.1 Event model)
			addMouseListener(new MouseKit());
			addMouseMotionListener(new MouseMotionKit());
		
	
			// See if there are images for the markers
			if (createCloseImage) {
				if (imageTrack == null) 
					imageTrack = new MediaTracker(this);
				closeImageURL = returnImageURL(closeImageName);
				this.closeImage = Toolkit.getDefaultToolkit().getImage(closeImageURL);
				// imageTrack.addImage(closeImage,imageCount++);
				imageTrack.addImage(closeImage,1);
			}
	
			if (createOpenImage) {
				if (imageTrack == null) 
					imageTrack = new MediaTracker(this);
				openImageURL = returnImageURL(openImageName);
				openImage = Toolkit.getDefaultToolkit().getImage(openImageURL);
				// imageTrack.addImage(openImage,imageCount++);
				imageTrack.addImage(openImage,2);
			} 
		} catch (Exception e) {
    		e.printStackTrace();
    	} // try...catch
	} // KioskCanvas Constructor


	/*
	 ****************************************************************
	 * Main methods.
	 ****************************************************************
	 */
	public URL returnImageURL(String imageName) {
		URL returnURL 	= null;
		String fileDir;
		int baseNameIndex;
		
		
		// The name of the dir to a string
 		fileDir = Node.docDir.toString();
 		baseNameIndex = fileDir.lastIndexOf("/");
 		baseNameIndex += 1;
 		
 		// Take out the name of the actual file and leave the directory.
	 	fileDir = fileDir.substring(0,baseNameIndex);
 		
 		// Append the file name to the URL
 		fileDir += "../graphics/" + imageName;
 		
 		// Create the URL to return
 		try {
 			returnURL = new URL(fileDir);
 		} catch (MalformedURLException exc) {
 			System.err.println("There was an error in loading your image. The default images will be used.");
		} 
	
		// Return the URL to load
		return returnURL;
	
	} // returnImageURL
	 
 
	/**
	 * The line that seperates the Nodes.<br>
	 * Used to determine what to do (if over text or marker, etc).
	 *
	 * @param	y	The vertical position of the mouse.
	 *
	 * @return	Returns the Y position to know what node we are over.
	 */
	int mouseLine(int y) {
		return (y - (Node.nodeLeading/2)) / Node.nodeLeading;
	}
   
	

	/*
	 ****************************************************************
	 * Overridden methods.
	 ****************************************************************
	 */
	public void paint(Graphics g) {
		// Where we are positioned
		int ypos = 0;

		// Set up and create the buffered image.
		if (bufferImage == null) {
			bufferImage = createImage(appWidth,appHeight);
    		bufferGraphics = bufferImage.getGraphics();
		}

		// Set the background for the buffered image
		bufferGraphics.setColor(bgColor);
		bufferGraphics.fillRect(0,0,appWidth,appHeight);
		
		// Check and make sure that all the original images
		// have finished loading before we start painting
		// the buffered image.
		if (imageTrack != null) {
			// wait for graphics to load
			try {
				imageTrack.waitForAll(); 
			} catch (InterruptedException e) {
				System.out.println("Problem waiting for images to load...");
			}
		}

 		// Set the font to start drawing
		bufferGraphics.setColor(Node.fontColor);
  	
  		// Make sure our Vector is clean
  		treeDisplay.removeAllElements();
  	
  
  		// Add the current state of the nodes to the buffered image.
  		for (Enumeration e = parentApp.cd0Tree.elements(); e.hasMoreElements();) {
			Node n = (Node)e.nextElement();
			ypos = n.paintNode(bufferGraphics,treeDisplay,20,ypos+Node.nodeLeading);
		}
		
		// Draw the completed buffered image to the main display component.
		g.drawImage(bufferImage,0,0,this);
	} // paint()


	public void update(Graphics g) {
  		paint(g);
	} // update()
	
	
	
	/*
	 ****************************************************************
	 * Get/Set State methods.
	 ****************************************************************
	 */
	 
	/**
	 * Set the background of the canvas component.
	 *
	 * @param newColor The new color to set the background color
	 */
	public void setBGColor(Color newColor) {
		this.bgColor = newColor;
	} // setBGColor
	
	/**
	 * Return the current bgColor
	 */
	public Color getBGColor() {
		return this.getBackground();
	} // getBGColor
	
	/*
	 ****************************************************************
	 * Convenience methods.
	 ****************************************************************
	 */

	
	/**
	 * Sends a comment to the console for printing.
	 *
	 * @param	comment	The string to print to the console.
	 */
	public void console(String comment) {
		 System.out.println(comment);  
	} // console()
	
	/*
	 ****************************************************************
	 * Inner Classes.
	 ****************************************************************
	 */
	
	/**
	 * Set up MouseAdapter to listen for when the mouse is clicked 
	 * and for when the mouse leaves the active area.
	 */
	class MouseKit extends MouseAdapter {
		public void mouseClicked(MouseEvent e) {
			int xPos = e.getX();
			int yPos = e.getY();
			int line;
			
			
			// Set up the divider line to tell where we are
			// and what to do
			line = mouseLine(yPos);
			
			// Now test the lines
			if (line < 0)
				return;
				
			// Out of the active area? Repaint all off....
			if (line > treeDisplay.size() - 1) {
				if (Node.mouseOver != null) {
					Node.mouseOver = null;
					parentApp.totalRepaint = true;
				}
				
				// Return control
				return;
			}
			
			// Create the NodeReg (info on this node)
			RegNode reg = (RegNode)treeDisplay.elementAt(line);
			
			// Are we right or left of the line?
			// Tell what to do in Node depending on location
			if (xPos < reg.x) 
				reg.node.leftAction(parentApp);
			else
				reg.node.rightAction(parentApp);
				
			// Repaint the whole applet to give feedback
			parentApp.totalRepaint = true;
			
			// Return control
			return;
		} // mouseClicked()
		
		public void mouseExited(MouseEvent e) {
			if (Node.mouseOver != null) {
				Node.mouseOver = null;
				parentApp.totalRepaint = true;
			} 
			
			// Return control
			return;
		
		} // mouseExited()
	
	} // MouseKit()
	
	/**
	 * Set up the MouseMotion for when the mouse is moved, 
	 * and determining what to do.
	 */
	class MouseMotionKit extends MouseMotionAdapter {
		public void mouseMoved(MouseEvent e) {
			int xPos = e.getX();
			int yPos = e.getY();
			int line;
			
			// Set up the divider line to tell where we are
			// and what to do
			line = mouseLine(yPos);
			
			// Now test the lines
			if (line < 0)
				return;
				
			// Out of the active area? Repaint all off....
			if (line > treeDisplay.size() - 1) {
				if (Node.mouseOver != null) {
					Node.mouseOver = null;
					parentApp.totalRepaint = true;
				}
				
				// Return control
				return;
			}
			
			// Create the NodeReg (info on this node)
			RegNode reg = (RegNode)treeDisplay.elementAt(line);
			
			// Are we right or left of the line?
			// Tell what to do in Node depending on location
			if (xPos < reg.x) 
				reg.node.leftStatus(parentApp);
			else
				reg.node.rightStatus(parentApp);
				
			// Repaint the whole applet to give feedback
			parentApp.totalRepaint = true;
			
			// Return control
			return;
		} // mouseMoved();
	
	
	
	} // MouseMotionKit()
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

} // KioskCanvas
