import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * this class makes MS paint..in java
 * 
 * @author <Brad Holland & Jennifer Kotsybar>. Started work <4/8/08>
 */
public class Paint extends JPanel implements ActionListener, ChangeListener
{

	private static final int FRAME_WIDTH = 1200;

	private static final int FRAME_HEIGHT = 1000;

	// what the min value of the slider is
	private static final int MIN = 0;

	// what the max value of the slider is
	private static final int MAX = 50;

	// what the slider initialized to
	private static final int INIT = 1;

	private final Canvas canvas = new Canvas();

	// private Brush brush = new Brush("Brush");

	private final Pencil pencil = new Pencil("Pencil");

	private final Rectangle rectangle = new Rectangle("Rectangle");

	private final Line line = new Line("Line");

	private final Oval oval = new Oval("Oval");

	private final Polygon polygon = new Polygon("Polygon");

	private final Undo undo = new Undo("Undo");

	private final ClearAll clearAll = new ClearAll("ClearAll");

	private final JCheckBox fill = new JCheckBox("Fill");

	private final JCheckBox unFill = new JCheckBox("Clear Fill");

	private final JSlider width = new JSlider(SwingConstants.VERTICAL, Paint.MIN, Paint.MAX, Paint.INIT);

	/**
	 * this is our JColorchooser for changing the colors of everything
	 */
	protected JColorChooser ColorChooser = new JColorChooser();

	/**
	 * constructs a frame and inserts the paint components
	 * 
	 * @param args
	 */
	public static void main(final String[] args)
	{
		final JFrame frame = new JFrame();
		frame.setSize(Paint.FRAME_WIDTH, Paint.FRAME_HEIGHT);
		frame.setTitle("Paint");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		final Paint component = new Paint();
		frame.add(component);
		frame.setVisible(true);
	}

	/**
	 * Paint constructor, creates a panel of grid layouts
	 * 
	 */
	public Paint()
	{
		// creates a new panel and sets the layout
		final JPanel workspace = new JPanel();
		workspace.setLayout(new BorderLayout());
		// creates a new panel with vertical stack layout
		final JPanel Buttons = new JPanel();
		Buttons.setPreferredSize(new Dimension(120, 600));
		Buttons.setLayout(new BoxLayout(Buttons, BoxLayout.Y_AXIS));

		// sets canvas to focusable so keyboard listener works
		this.canvas.setPreferredSize(new Dimension(1055, 600));
		this.canvas.setFocusable(true);
		this.canvas.setBackground(Color.WHITE);

		// Buttons.add(this.brush);
		// this.brush.addActionListener(this);

		// adds buttons and respective listeners
		Buttons.add(this.pencil);
		this.pencil.addActionListener(this);

		Buttons.add(this.line);
		this.line.addActionListener(this);

		Buttons.add(this.polygon);
		this.polygon.addActionListener(this);

		Buttons.add(this.rectangle);
		this.rectangle.addActionListener(this);

		Buttons.add(this.oval);
		this.oval.addActionListener(this);

		Buttons.add(this.undo);
		this.undo.addActionListener(this);

		Buttons.add(this.clearAll);
		this.clearAll.addActionListener(this);

		Buttons.add(this.fill);
		this.fill.addActionListener(this);

		this.unFill.setSelected(true);
		Buttons.add(this.unFill);
		this.unFill.addActionListener(this);

		// adds listener to slider
		// sets up tick marks & labels
		this.width.addChangeListener(this);
		this.width.setMajorTickSpacing(10);
		this.width.setMinorTickSpacing(5);
		this.width.setPaintTicks(true);
		this.width.setPaintLabels(true);
		Buttons.add(this.width);
		Buttons.add(new JLabel("Thickness"));

		this.ColorChooser.getSelectionModel().addChangeListener(this);

		// adds a border to the canvas
		this.canvas.setBorder(BorderFactory
				.createEtchedBorder(EtchedBorder.RAISED));
		final JPanel ColorChooserGrid = new JPanel();

		ColorChooserGrid
				.add(new JLabel(
						"Hold Shift while using rectangle and oval for perfect Squares and Circles"));
		ColorChooserGrid.add(this.ColorChooser);
		ColorChooserGrid.add(new JLabel("By Brad Holland & Jennifer Katsybar"));
		// adds JPanels...nested
		workspace.add(Buttons, BorderLayout.WEST);
		workspace.add(ColorChooserGrid, BorderLayout.SOUTH);
		workspace.add(this.canvas, BorderLayout.EAST);
		this.add(workspace);

	}

	public void actionPerformed(final ActionEvent e)
	{
		// the following methods are a form of communication between paint and
		// canvas, when a button is pressed a string is sent to the canvas
		// identifying which tool is selected

		if (e.getSource() == this.pencil)
		{
			// System.out.println("pencil");
			this.canvas.setTool("pencil");
		}

		if (e.getSource() == this.rectangle)
		{
			// System.out.println("rectangle");
			this.canvas.setTool("rectangle");
		}

		if (e.getSource() == this.line)
		{
			// System.out.println("line");
			this.canvas.setTool("line");
		}

		if (e.getSource() == this.polygon)
		{
			// System.out.println("polygon");
			this.canvas.setTool("polygon");
		}

		if (e.getSource() == this.undo)
		{
			// System.out.println("undo");
			// this.canvas.setTool("undo");
			this.canvas.Undo();
		}

		if (e.getSource() == this.oval)
		{
			// System.out.println("oval");
			this.canvas.setTool("oval");
		}

		if (e.getSource() == this.clearAll)
		{
			// System.out.println("clearAll");
			// this.canvas.setTool("clearAll");
			this.canvas.clearAll();
		}

		if (e.getSource() == this.fill)
		{
			this.canvas.setFill(true);
			this.unFill.setSelected(false);
		}

		if (e.getSource() == this.unFill)
		{
			this.canvas.setFill(false);
			this.fill.setSelected(false);
		}

	}

	public void stateChanged(final ChangeEvent e)
	{
		// determines if a color from the chooser has been selected
		if (e.getSource() == this.ColorChooser.getSelectionModel())
		{
			// if its selected set that as the current color
			final Color newColor = this.ColorChooser.getColor();
			this.canvas.setColor(newColor);
		}

		if (e.getSource() == this.width)
		{
			final JSlider source = (JSlider) e.getSource();
			if (!source.getValueIsAdjusting())
			{
				// as soon as the slider is done adjusting set the width
				this.canvas.setWidth(source.getValue());
			}
		}

	}
}
