/*
 *  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 java.util.ArrayList;

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

import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JDialog;
import javax.swing.JTextField;

import com.approximatrix.draco.application.ApplicationManager;
import com.approximatrix.draco.application.ChildFrame;
import com.approximatrix.draco.datamodel.StatTableModel;
import com.approximatrix.draco.datamodel.Constant;

import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class ConstantsDialog extends ChildFrame implements ActionListener {

	private static final String DIALOG_NAME = "Constants";
	
	/** The string for requesting topical help */
	private static final String HELP_KEY = "constants";
	
	/** The icon to be displayed for this child window */
	private static final String PATH_TO_ICON = "/com/approximatrix/draco/main/ui/images/constant.png";
	
	
	private JDialog myself = null;
	private JPanel jContentPane = null;
	private JScrollPane jScrollPane = null;
	private JTable jConstantsTable = null;
	private StatTableModel parentmodel = null;
	private ConstantsTableModel model = null;
	
	private JButton add_button = null;
	private JButton rem_button = null;

	/**
	 * This is the default constructor
	 */
	public ConstantsDialog(StatTableModel main_model) {
		//super(manager.getMainWindow());
		super(DIALOG_NAME, 
				true, //resizable
				true, //closable
				true, //maximizable
				true);

		this.parentmodel = main_model;
		
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(300, 350);
		this.setTitle(DIALOG_NAME);
		this.setContentPane(getJContentPane());
		super.setIcon(PATH_TO_ICON);
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJScrollPane(), java.awt.BorderLayout.CENTER);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setViewportView(getJConstantsTable());
		}
		return jScrollPane;
	}

	/**
	 * This method initializes jConstantsTable	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JTable getJConstantsTable() {
		if (jConstantsTable == null) {
			
			// Initialize the tablemodel
			model = new ConstantsTableModel(parentmodel.getConstants());
			jConstantsTable = new JTable();
			jConstantsTable.setModel(model);
			jConstantsTable.setColumnSelectionAllowed(false);
			jConstantsTable.setCellSelectionEnabled(false);
			jConstantsTable.setRowSelectionAllowed(true);
		}
		return jConstantsTable;
	}
	
	/** Forces an update of the constants table
	 *
	 */
	public void fireConstantsChange() {
		model.fireTableDataChanged();
		model.fireTableStructureChanged();
	}
	
	/** No menu options are necessary for the Constants window for now
	 * 
	 * @return null since there are no buttons
	 * @see com.approximatrix.draco.application.ChildFrame#getMenuItems()
	 */
	public JMenu[] getMenuItems() {
		// TODO Auto-generated method stub
		return null;
	}

	/** Constructs the "add" and "remove" buttons for the  toolbar for the
	 * constants window
	 * 
	 * @return an array of buttons for the toolbar
	 * @see com.approximatrix.draco.application.ChildFrame#getToolbarButtons()
	 */
	public Component[] getToolbarButtons() {
		if(toolbarButtons == null) {
			ArrayList<Component> buttons = new ArrayList<Component>();
			
			// Add on the buttons
			add_button = new JButton();
			add_button.setToolTipText("Add a constant");
			add_button.setIcon(ApplicationManager.GetIcon("ADD"));
			add_button.addActionListener(this);
			buttons.add(add_button);
			
			rem_button = new JButton();
			rem_button.setToolTipText("Remove selected");
			rem_button.setIcon(ApplicationManager.GetIcon("REMOVE"));
			rem_button.addActionListener(this);
			buttons.add(rem_button);
			
			toolbarButtons = new Component[buttons.size()];
			buttons.toArray(toolbarButtons);
		}
		return toolbarButtons;
	}

	/** The Constants window should not be renamed ever.
	 * 
	 * @return false
	 * @see com.approximatrix.draco.application.ChildFrame#isRenameable()
	 */
	public boolean isRenameable() {
		return false;
	}

	/** Handles all events for the two buttons that the constants dialog uses
	 * 
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent arg0) {
		Object source = arg0.getSource();
		
		if(source == add_button) {
			JTextField textfield = new JTextField();
			textfield.setText("New_Constant");
			Object[] options = {"Ok","Cancel"};
			int selection = JOptionPane.showOptionDialog(myself,
														 textfield,
														 "Enter a name for new constant",
														 JOptionPane.YES_NO_OPTION,
														 JOptionPane.QUESTION_MESSAGE,
														 null,
														 options,
														 options[0]);
			if(selection == 0) {
				model.addConstant(textfield.getText());
				textfield = null;
			}
		} else if(source == rem_button) {
			int row = getJConstantsTable().getSelectedRow();
			model.removeConstant(row);
		}
			
	}

	private class ConstantsTableModel extends AbstractTableModel {
	    private String[] columnNames = {"Constant","Value"};
	    private ArrayList constants = null;

	    public ConstantsTableModel(ArrayList values) {
	    	constants = values;
	    }
	    
	    public int getColumnCount() {
	        return 2;
	    }

	    public int getRowCount() {
	    	if(constants == null)
	    		return 0;
	    	else
	    		return constants.size();
	    }

	    public String getColumnName(int col) {
	        return columnNames[col];
	    }

	    public Object getValueAt(int row, int col) {
	    	Constant one = (Constant)constants.get(row);
	    	if(col == 0)
	    		return one.getName();
	    	else 
	    		return one.getValue();
	    }

	    public Class getColumnClass(int col) {
	    	if(col == 0)
	    		return String.class;
	    	else
	    		return Double.class;
	    }

	    /*
	     * Don't need to implement this method unless your table's
	     * editable.
	     */
	    public boolean isCellEditable(int row, int col) {
	        //Note that the data/cell address is constant,
	        //no matter where the cell appears onscreen.
	        if (col == 0)
	            return false;
	        else
	            return true;
	    }

	    /*
	     * Don't need to implement this method unless your table's
	     * data can change.
	     */
	    public void setValueAt(Object value, int row, int col) {
	    	Constant entry = (Constant)constants.get(row);
	    	entry.setValue((Double)value);
	        fireTableCellUpdated(row, col);
	    }
	    
	    private boolean isConstant(String name) {
	    	boolean found = false;
	    	for(int i=0;i<constants.size() && !found;i++) {
	    		found = ((Constant)constants.get(i)).getName().compareTo(name) == 0;
	    	}
	    	return found;
	    }
	    
	    public void addConstant(String name) {
	    	if(!isConstant(name)) {
	    		Constant to_add = new Constant(name);
	    		constants.add(to_add);
	    		fireTableStructureChanged();
	    		fireTableDataChanged();
	    	}
	    }
	    
	    public void removeConstant(String name) {
	    	for(int i=0;i<getRowCount();i++) {
	    		if(name.compareTo((String)getValueAt(i,0))==0) {
	    			constants.remove(i);
	    			break;
	    		}
	    	}
	    	fireTableStructureChanged();
			fireTableDataChanged(); 
	    }
	    
	    public void removeConstant(int row) {
	    	if(row >= 0 && row < getRowCount()) {
	    		constants.remove(row);
	    	}
	    	fireTableStructureChanged();
			fireTableDataChanged(); 
	    }
	    
	}
	
	/** Returns the help key for the Column Statistics window
	 * 
	 * @return the proper help key, defined by HELP_KEY
	 * @see #HELP_KEY
	 * @see com.approximatrix.draco.application.ChildFrame#getHelpKey()
	 */
	public String getHelpKey() {
		return HELP_KEY;
	}
	
}  //  @jve:decl-index=0:visual-constraint="89,12"
