/*
 *  Draco Econometrics
 *  Copyright (C) 2006-2007 Approximatrix, LLC
 *  http://www.approximatrix.com
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.approximatrix.draco.main.ui;

import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Component;

import com.approximatrix.draco.application.ApplicationManager;
import com.approximatrix.draco.application.ChildFrame;

public class DynamicToolbar extends JToolBar implements ActionListener {
	
	/** Location in the default menu bar to insert new JMenu's when adding dynamic elements */
	private static final int INSERT_POSITION_FROM_RIGHT = 2;
	
	private MainWindow parent = null;
	
	// The buttons
	private JButton new_button = null;
	private JButton open_button = null;
	private JButton save_button = null;
	private JButton saveas_button = null;
	
	private JButton print_button = null;
	private JButton close_button = null;
	
	private JButton constants_button = null;
	
	private JButton help_button = null;
	
	private JButton rename_button = null;
	
	private ChildFrame last = null;
	
	
	
	/** Creates and returns a generic Cut button for inclusion on a
	 * toolbar.  
	 * 
	 * @return a cut button for a toolbar
	 */
	public static JButton GetGenericCutButton(final MainWindow parent) {
		JButton cut_button = new JButton();
		cut_button.setToolTipText("Cut selection");
		cut_button.setIcon(GetIcon("EDITCUT"));
		cut_button.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				parent.getMainMenuBar().signalCut();
			}
		});
		
		return cut_button;
	}
	
	/** Creates and returns a generic Copy button for inclusion on a
	 * toolbar. 
	 * 
	 * @return a copy button for a toolbar
	 */
	public static JButton GetGenericCopyButton(final MainWindow parent) {
		JButton copy_button = new JButton();
		copy_button.setToolTipText("Copy selection");
		copy_button.setIcon(GetIcon("EDITCOPY"));
		copy_button.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				parent.getMainMenuBar().signalCopy();
			}
		});
		return copy_button;
	}
	
	/** Creates and returns a generic Paste button for inclusion on a
	 * toolbar.  
	 * 
	 * @return a paste button for a toolbar
	 */
	public static JButton GetGenericPasteButton(final MainWindow parent) {
		JButton paste_button = new JButton();
		paste_button.setToolTipText("Paste from clipboard");
		paste_button.setIcon(GetIcon("EDITPASTE"));
		paste_button.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent e) {
				parent.getMainMenuBar().signalPaste();
			}
		});
		return paste_button;
	}
	
	/** Constructor for building a toolbar for the main window that allows
	 * modification based on the child in focus
	 * 
	 * @param parent the MainWindow object that owns this toolbar
	 */
	public DynamicToolbar(MainWindow parent) {
		super();
		this.parent = parent;
		this.setFloatable(true);
		initialize();
	}
	
	/** Initializes the constant buttons
	 */
	private void initialize() {
		
		// Basic File ops
		super.add(getNew_button());
		super.add(getOpen_button());
		super.add(getSave_button());
		super.add(getSaveas_button());
		
		// Not implemented for all children...
		//super.add(getPrint_button());
		super.add(getClose_button());
		
		super.addSeparator();

		super.add(getConstants_button());
		
		// Help
		super.add(Box.createHorizontalGlue());
		super.add(getHelp_button());
		
		// Create, but don't add, the rename button
		rename_button = new JButton();
		rename_button.setToolTipText("Rename current dialog");
		rename_button.setIcon(ApplicationManager.GetIcon("RENAME"));
		rename_button.addActionListener(this);

	}
	
	/** Called when a new frame is focussed in the MainWindow.  Extracts
	 * the menu items and places them in the MDI menu.
	 * 
	 * @param infront 
	 */
	public void setFocusedChild(ChildFrame infront) {
		if(last != null) {
			removeItems(last.getToolbarButtons());
			if(last.isRenameable())
				this.remove(rename_button);
		}
		if(infront != null) {
			addItems(infront.getToolbarButtons());
			if(infront.isRenameable())
				this.add(rename_button,this.getComponentIndex(getHelp_button())-1);
		}
		
		last = infront;
		
		// Execute the Swing update later
		//Runnable updateBar = new Runnable() {
        //   public void run() {
        //    	DynamicToolbar.super.
        //    	DynamicToolbar.super.doLayout();
        //    	DynamicToolbar.super.repaint();
        //    }
        //};
        //SwingUtilities.invokeLater(updateBar);
		super.validate();
		super.repaint();
	}
	
	/** Adds the specified array of components to the toolbar, inserting them before
	 * the help button and its HorizontalGlue.
	 * 
	 * @param buttons the buttons to add
	 */
	private void addItems(Component[] buttons) {
		if(buttons == null) return;
		for(int i=0;i<buttons.length;i++) {
			this.add(buttons[i], this.getComponentCount()-INSERT_POSITION_FROM_RIGHT);
		}
	}
	
	/** Removes the specified array of components from the toolbar
	 * 
	 * @param buttons the buttons, etc. to remove (can include separators)
	 */
	private void removeItems(Component[] buttons) {
		if(buttons == null) return;
		for(int i=0;i<buttons.length;i++) {
			this.remove(buttons[i]);
		}
	}
	
	/** Handles all menu actions using a nice, giant "if" structure
	 * 
	 */
	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();
		
		if(source == rename_button)
			renameCurrent();
		else if(source == new_button)
			parent.getMainMenuBar().newWorksheet(false);
		else if(source == open_button)
			parent.getMainMenuBar().loadWorksheet();
		else if(source == save_button)
			parent.getMainMenuBar().saveWorksheet(false);
		else if(source == saveas_button)
			parent.getMainMenuBar().saveWorksheet(true);
		else if(source == close_button)
			parent.closeWindow();
		else if(source == constants_button)
			parent.getMainMenuBar().viewConstants();
		else if(source == help_button)
			ApplicationManager.RequestHelp(last.getHelpKey());
	}
	
	private JButton getNew_button() {
		if(new_button == null) {
			new_button = new JButton();
			new_button.setToolTipText("New panel data worksheet...");
			new_button.setIcon(GetIcon("NEW"));
			new_button.addActionListener(this);
		}
		return new_button;
	}
	
	private JButton getOpen_button() {
		if(open_button == null) {
			open_button = new JButton();
			open_button.setToolTipText("Open an existing worksheet...");
			open_button.setIcon(GetIcon("OPEN"));
			open_button.addActionListener(this);
		}
		return open_button;
	}
	
	private JButton getSave_button() {
		if(save_button == null) {
			save_button = new JButton();
			save_button.setToolTipText("Save current worksheet...");
			save_button.setIcon(GetIcon("SAVE"));
			save_button.addActionListener(this);
		}
		return save_button;
	}
	
	private JButton getSaveas_button() {
		if(saveas_button == null) {
			saveas_button = new JButton();
			saveas_button.setToolTipText("Save current worksheet to a specified filename...");
			saveas_button.setIcon(GetIcon("SAVEAS"));
			saveas_button.addActionListener(this);
		}
		return saveas_button;
	}
	
	private JButton getPrint_button() {
		if(print_button == null) {
			print_button = new JButton();
			print_button.setToolTipText("Print the worksheet...");
			print_button.setIcon(new ImageIcon(getClass().getResource("/com/approximatrix/draco/main/ui/images/fileprint.png")));
			print_button.addActionListener(this);
		}
		return print_button;
	}
	
	private JButton getClose_button() {
		if(close_button == null) {
			close_button = new JButton();
			close_button.setToolTipText("Close this worksheet...");
			close_button.setIcon(GetIcon("CLOSE"));
			close_button.addActionListener(this);
		}
		return close_button;
	}
	
	private JButton getConstants_button() {
		if(constants_button == null) {
			constants_button = new JButton();
			constants_button.setToolTipText("View constants...");
			constants_button.setIcon(ApplicationManager.GetIcon("CONSTANTS"));
			constants_button.addActionListener(this);
		}
		return constants_button;
	}
	
	private JButton getHelp_button() {
		if(help_button == null) {
			help_button = new JButton();
			help_button.setToolTipText("Help...");
			help_button.setIcon(GetIcon("HELP"));
			help_button.addActionListener(this);
			
			//help_button.addMouseListener(new java.awt.event.MouseAdapter() { 
			//	public void mouseClicked(java.awt.event.MouseEvent e) {
			//		ApplicationManager.RequestHelp("MainWindow");
			//	}
			//});
		}
		return help_button;
	}
	
	/** Renames the currently focussed dialog (using the "last" object stored
	 * in the class instance).
	 *
	 */
	private void renameCurrent() {
		String current_name = last.getTitle();
		
		JTextField entry = new JTextField(current_name);
		
		Object[] buttons = {"Accept", "Cancel"};
		
		int result = JOptionPane.showOptionDialog(parent,
				                                  entry,
				                                  "Rename Dialog",
				                                  JOptionPane.YES_NO_OPTION,
				                                  JOptionPane.PLAIN_MESSAGE,
				                                  null,
				                                  buttons,
				                                  buttons[0]);
		
		if(result == 0) {
			last.setTitle(entry.getText());
			
			// Force a redraw of the Windows menu
			parent.getMainMenuBar().updateWindowsList();
		}
		
		entry = null;
	}
	
	public static Icon GetIcon(String key) {
		return ApplicationManager.GetIcon(key);
	}
	
}
