import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;


/**
 * Implements a Menu with sub menus
 *
 * @author swansom1.
 *         Created Apr 14, 2008.
 */
public class MenuBar extends JMenuBar implements ActionListener {

	private JMenuBar menuBar = new JMenuBar();
	private JMenu file = new JMenu("Menu");
	private JMenu edit = new JMenu("Edit");
	private JMenu image = new JMenu("Image");
	private JMenuItem fileNew = new JMenuItem("New");
	private JMenuItem fileOpen = new JMenuItem("Open");
	private JMenuItem fileSave = new JMenuItem("Save");
	private JMenuItem fileExit = new JMenuItem("Exit");
	private JMenuItem editUndo = new JMenuItem("Undo");
	private JMenuItem editRedo = new JMenuItem("Redo");
	private JMenuItem imageClear = new JMenuItem("Clear Image");
	private CanvasPanel canvas;
	private ArrayList<Object> redoDrawArray = new ArrayList<Object>(5);
	private ArrayList<Color> redoColorArray = new ArrayList<Color>(5);
	private ArrayList<BasicStroke> redoStrokeArray = new ArrayList<BasicStroke>(5);
	private boolean undo = false;
	private boolean redo = false;
	private String withExtension;
	private String name;
	
	
	/**
	 * Creates a new MenuBar to be put in Paint frame.
	 * 
	 * @param canvas
	 */
	public MenuBar(CanvasPanel canvas) {
		super();
		this.canvas = canvas;
		this.canvas.toString();
		this.fileNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
		this.fileNew.addActionListener(this);
		this.fileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
		this.fileOpen.addActionListener(this);
		this.fileSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
		this.fileSave.addActionListener(this);
		this.fileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
		this.fileExit.addActionListener(this);
		this.editUndo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
		this.editUndo.addActionListener(this);
		this.editRedo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.CTRL_MASK));
		this.editRedo.addActionListener(this);
		int action = ActionEvent.CTRL_MASK | ActionEvent.SHIFT_MASK;
		this.imageClear.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, action));
		this.imageClear.addActionListener(this);
		this.file.add(this.fileNew);
		this.file.add(this.fileOpen);
		this.file.add(this.fileSave);
		this.file.add(this.fileExit);
		this.menuBar.add(this.file);
		this.edit.add(this.editUndo);
		this.edit.add(this.editRedo);
		this.menuBar.add(this.edit);
		this.image.add(this.imageClear);
		this.menuBar.add(this.image);
		this.canvas.setMenuBar(this);
	}

	public void actionPerformed(ActionEvent e) {
		JMenuItem source = (JMenuItem)(e.getSource());
		if(source.getText() == "New"){
			Paint.main(null);
		}
		if(source.getText() == "Open"){
			openFile();
		}
		if(source.getText() == "Save"){  
			saveFile();
		}
		if(source.getText() == "Exit"){
			System.exit(1);
		}
		if(source.getText() == "Undo"){
			this.undo = true;
			setArray(this.canvas.getDrawArray(), this.canvas.getColorArray(), this.canvas.getStrokeArray());
		}
		if(source.getText() == "Redo"){
			this.redo = true;
			setArray(this.canvas.getDrawArray(), this.canvas.getColorArray(), this.canvas.getStrokeArray());
		}
		if(source.getText() == "Clear Image"){
			clearArray(this.canvas.getDrawArray(),this.canvas.getColorArray(), this.canvas.getStrokeArray());
		}
	}
	
	/**
	 * opens a user defined file
	 *
	 */
	private void openFile() {

		this.name = JOptionPane.showInputDialog("Enter the name of the file to open without the extension");
		if(this.name.contains(".")){
			this.withExtension = this.name;
		}else{
			this.withExtension = this.name + ".png";
		}
		File f = new File(this.withExtension);
		try {
			clearArray(this.canvas.getDrawArray(),this.canvas.getColorArray(),this.canvas.getStrokeArray());
			this.canvas.setBufferedImage(ImageIO.read(f));
		} catch (IOException exception) {
			JOptionPane.showMessageDialog(this, "No file found with that name", "File Not Found",JOptionPane.ERROR_MESSAGE);
		}
	}
	
	/**
	 * saves the image to a user defined file
	 *
	 */

	private void saveFile(){
		
		this.name = JOptionPane.showInputDialog("Enter the name of the file to save to without the extension");
		if(this.name.contains(".")){
			this.withExtension = this.name;
		}else{
			this.withExtension = this.name + ".png";
		}
		
		File f = new File(this.withExtension);
		
		try {
			ImageIO.write(this.canvas.getBufferedImage(), "png", f);
		} catch (IOException exception) {
			JOptionPane.showMessageDialog(this, "Failed to write image to file", "File Write Failed",JOptionPane.ERROR_MESSAGE);
		}
    }

	/**
	 * clears the passed in Arrays
	 * 
	 * 
	 * @param drawArray 
	 * @param strokeArray 
	 * @param colorArray
	 */
	public void clearArray(ArrayList<Object> drawArray, ArrayList<Color> colorArray, ArrayList<BasicStroke> strokeArray) {
		for(int i = drawArray.size()-1; i >= 0; i--){
			drawArray.remove(i);
			colorArray.remove(i);
			strokeArray.remove(i);
		}
		this.canvas.setDrawArray(drawArray);
		this.canvas.setColorArray(colorArray);
		this.canvas.setStrokeArray(strokeArray);
	}

	/**
	 * sets the current arrays to the passed in arrays
	 *
	 * @param drawArray
	 * @param colorArray 
	 * @param strokeArray 
	 */
	public void setArray(ArrayList<Object> drawArray, ArrayList<Color> colorArray, ArrayList<BasicStroke> strokeArray) {
			
		if (this.undo == true && drawArray.size() >= 1) {
				this.redoDrawArray.add(drawArray.get(drawArray.size() - 1));
				this.redoColorArray.add(colorArray.get(colorArray.size() - 1));
				this.redoStrokeArray.add(strokeArray.get(strokeArray.size() - 1));
	
				drawArray.remove(drawArray.size() - 1);
				colorArray.remove(colorArray.size() - 1);
				strokeArray.remove(strokeArray.size() - 1);
	
				this.canvas.setDrawArray(drawArray);
				this.canvas.setColorArray(colorArray);
				this.canvas.setStrokeArray(strokeArray);
				this.canvas.setCheck();
				this.undo = false;
				this.redo = false;
		}
		if (this.redo == true && this.redoDrawArray.size() >= 1) {

			drawArray.add(this.redoDrawArray.get(this.redoDrawArray.size() - 1));
			colorArray.add(this.redoColorArray.get(this.redoColorArray.size() - 1));
			strokeArray.add(this.redoStrokeArray.get(this.redoStrokeArray.size() - 1));

			this.redoDrawArray.remove(this.redoDrawArray.size() - 1);
			this.redoColorArray.remove(this.redoColorArray.size() - 1);
			this.redoStrokeArray.remove(this.redoStrokeArray.size() - 1);

			this.canvas.setDrawArray(drawArray);
			this.canvas.setColorArray(colorArray);
			this.canvas.setStrokeArray(strokeArray);
			this.redo = false;
			this.undo = false;
		}
	}

	/**
	 * returns the menubar
	 *
	 * @return The menu bar
	 */
	public JMenuBar getJMenuBar() {
		return this.menuBar;
	}

	/**
	 * clears the redo arrays
	 *
	 */
	public void clearRedo() {
		this.redoDrawArray.clear();
		this.redoColorArray.clear();
		this.redoStrokeArray.clear();
	}

}
