/*
        Class example illustrating the use of Panels w/choice and TextField
        Also demonstrates use of arrays.
        Written 10/3/99 by Kim Bruce
        
        Modified by Barbara Lerner 10/28/03 
        Now uses Swing
        Added the Recolor Item command to demonstrate searching the array
        without actually changing the array contents.
*/
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import objectdraw.DrawableInterface;
import objectdraw.FilledOval;
import objectdraw.FilledRect;
import objectdraw.Location;
import objectdraw.WindowController;

public class Drawing extends WindowController {
	
	// max number of objects to be displayed
	private static final int SIZE = 100;
	private static final int MAX_OBJECTS = 20;
	
	// menus for shape, color, and command
	private JComboBox shapeChoice;
	private JComboBox colorChoice;
	private JComboBox commandChoice;
	
	// Array of objects on screen.
	private DrawableInterface[] shapes = new DrawableInterface[MAX_OBJECTS];
	
	// number of objects on screen
	private int numShapes = 0;
	
	// item currently selected for dragging
	private DrawableInterface selected;
	
	// mouse loc'n when last handled mouse
	private Location lastPoint;
	
	// Set up GUI components for program
	public void begin() {
		// create panel to hold choice buttons
		JPanel menuPanel = new JPanel();
	
		// menu for selecting or adding
		commandChoice = new JComboBox();
		commandChoice.addItem("Add new item");
		commandChoice.addItem ("Recolor item");
		commandChoice.addItem("Move item");
		commandChoice.addItem("Delete item");
		menuPanel.add(commandChoice);
	
		// Set up menu for shapes
		shapeChoice = new JComboBox();
		shapeChoice.addItem("Circle");
		shapeChoice.addItem("Square");
		menuPanel.add(shapeChoice);
	
		// Set up menu for colors
		colorChoice = new JComboBox();
		colorChoice.addItem("Red");
		colorChoice.addItem("Green");
		colorChoice.addItem("Blue");
		menuPanel.add(colorChoice);
	
		// Add the panel to screen
		getContentPane().add(menuPanel, BorderLayout.SOUTH);
	}
	
	// When the user clicks in the canvas, check the settings of the command menu to
	// determine what action to take.
	public void onMousePress(Location point) {
		selected = null; // indicate nothing currently selected
		Object buttonLabel = commandChoice.getSelectedItem();
		if (buttonLabel.equals("Add new item")) {
			addNew(point);
		} else if (buttonLabel.equals ("Recolor item")) {
			recolorShapeAt (point);
		} else if (buttonLabel.equals("Move item")) {
			selectShapeAt(point);
		} else {
			deleteShapeAt(point);
		}
	}
	
	// This method implements the "Add new item" command.
	// Add new geometric shape where clicked.  Type and color of object is determined by the
	// settings of the color and shape menus.
	private void addNew(Location point) {
		// only add if still room for more objects
		if (numShapes < MAX_OBJECTS) {
			Location point1 = new Location (point.getX() - SIZE/2, 
										   point.getY() - SIZE/2);
			Object shapeString = shapeChoice.getSelectedItem();
			DrawableInterface newShape;
				
			// create new object to be shape chosen
			if (shapeString.equals("Square")) {
				newShape =
					new FilledRect(point1, SIZE, SIZE, canvas);
			} else {
				newShape =
					new FilledOval(point1, SIZE, SIZE, canvas);
			}
				
			newShape.setColor(getSelectedColor());
			shapes[numShapes] = newShape;
			numShapes++;
		}
	}
	
	// Returns the color corresponding to the string selected in the
	// color menu.
	private Color getSelectedColor() {
		Color objectColor; // local variable - color of object
	
		// get color showing in the color menu
		Object colorString = colorChoice.getSelectedItem();
	
		// set objectColor to chosen color
		if (colorString.equals("Red")) {
			objectColor = Color.RED;
		} else if (colorString.equals("Green")) {
			objectColor = Color.GREEN;
		} else {
			objectColor = Color.BLUE;
		}
		return objectColor;
	}

	/*
	 * Change the shape and color of the item the user clicks on.
	 * This implements the "Update Item" command.  Since the update
	 */
	private void recolorShapeAt(Location point) {
		int selectIndex = getIndexOf(point);

		if (selectIndex != -1) {
			shapes[selectIndex].setColor (getSelectedColor());
		}
	}
	
	// return the index of the last element of shapes containing point
	// return -1 if no element of shapes contains point
	private int getIndexOf(Location point) {
		// Walk the array until we find the selected shape
		for (int selectIndex = numShapes - 1; selectIndex >= 0; selectIndex--) {
			if (shapes[selectIndex].contains(point)) {
				return selectIndex;
			}
		}
		return -1;
	}
	
	// Remove top-most geometric item clicked in.  If didn't click in any then don't do anything.
	private void deleteShapeAt(Location point) {
		int selectIndex = getIndexOf(point);
	
		// if point is in one of the objects, delete it
		if (selectIndex != -1) {
			shapes[selectIndex].removeFromCanvas();
			removeEltWithIndex(selectIndex);
			shapes[numShapes] = null;
		}
	}
	
	// remove shapes[index] by moving later elements back.
	private void removeEltWithIndex(int index) {
		for (int objNum = index; objNum < numShapes - 1; objNum++) {
			shapes[objNum] = shapes[objNum + 1];
		}
		numShapes--;
	}
	
	// Set select to indicate top-most geometric item clicked in, and send it to front of
	// screen.  If didn't click in any then select stays null.  Remember where clicked in
	// lastPoint.
	private void selectShapeAt(Location point) {
		int selectIndex = getIndexOf(point);
	
		// Remember which shape is selected so onMouseDrag can move it.
		if (selectIndex != -1) {
			selected = shapes[selectIndex];
			lastPoint = point;
			
			// Move the selected object to the front of the display
			// and to the end of the array if it is not already there
			if (selectIndex != numShapes-1) {
				selected.sendToFront();
				removeEltWithIndex(selectIndex);
				shapes[numShapes] = selected;
				numShapes++;
			}
		}
	}
	
	// If something was selected then drag it and remember where left off
	public void onMouseDrag(Location point) {
		if (selected != null) {
			selected.move(
				point.getX() - lastPoint.getX(),
				point.getY() - lastPoint.getY());
			lastPoint = point;
		}
	}
}
