/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.core.gui.widgets.hotkeys;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.AbstractCellEditor;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;

import lu.tudor.santec.gecamed.core.gui.GECAMedAction;
import lu.tudor.santec.gecamed.core.gui.listener.GlobalHotkeyRegister;
import lu.tudor.santec.i18n.Translatrix;

/**
 * jpanel to edit the hotkeys used in the GECAMed client
 * 
 * @author Johannes Hermen johannes.hermen(at)tudor.lu
 *
 * @Version
 * <br>$Log: HotkeyPanel.java,v $
 * <br>Revision 1.5  2011-03-04 09:53:11  ferring
 * <br>Hotkeys for physicians added.
 * <br>It is now possible to make a hotkey consisting of key + modifiers.
 * <br>
 * <br>Revision 1.4  2008-09-25 09:43:07  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.3  2008-01-15 09:29:38  hermen
 * <br>updated Javadoc and refactured code
 * <br>
 * <br>Revision 1.2  2007-12-04 14:59:04  hermen
 * <br>updated Javadoc and refactured code
 * <br>
 *
 */
public class HotkeyPanel extends JPanel{

	private static final long serialVersionUID = 1L;
	private JTable table;
	private HotkeyTableModel model;
	private Vector<GECAMedAction> actions;
	private String additionalKey = "Alt+";

	/**
	 * creates the panel
	 */
	public HotkeyPanel() {
		
		this.setLayout(new BorderLayout());
		
		this.model = new HotkeyTableModel();
		
		this.table = new JTable(model);
		this.table.getColumnModel().getColumn(1).setCellRenderer(new HotkeyRenderer(true));
		this.table.getColumnModel().getColumn(2).setCellRenderer(new HotkeyRenderer(false));
		
		this.table.getColumnModel().getColumn(1).setCellEditor(new HotkeyEditor(true));
		this.table.getColumnModel().getColumn(2).setCellEditor(new HotkeyEditor(false));
		
		this.table.getColumnModel().getColumn(1).setMaxWidth(150);
		this.table.getColumnModel().getColumn(1).setMinWidth(150);
		this.table.getColumnModel().getColumn(2).setMaxWidth(150);
		this.table.getColumnModel().getColumn(2).setMinWidth(150);
		
		this.add(this.table.getTableHeader(), BorderLayout.NORTH);
		this.add(this.table, BorderLayout.CENTER);
	}
	
	/**
	 * set the actions for the hotkeys that should be showed
	 * @param actions
	 */
	public void showActions(Vector<GECAMedAction> actions) {
		this.actions = actions;
		this.model.setActions(actions);
	}
	
	/**
	 * Tablemodel to manage the hotkeys
	 * 
	 * @author Johannes Hermen johannes.hermen(at)tudor.lu
	 *
	 * @Version
	 * <br>$Log: HotkeyPanel.java,v $
	 * <br>Revision 1.5  2011-03-04 09:53:11  ferring
	 * <br>Hotkeys for physicians added.
	 * <br>It is now possible to make a hotkey consisting of key + modifiers.
	 * <br>
	 * <br>Revision 1.4  2008-09-25 09:43:07  heinemann
	 * <br>fixed copyrights
	 * <br>
	 * <br>Revision 1.3  2008-01-15 09:29:38  hermen
	 * <br>updated Javadoc and refactured code
	 * <br>
	 * <br>Revision 1.2  2007-12-04 14:59:04  hermen
	 * <br>updated Javadoc and refactured code
	 * <br>
	 *
	 */
	public class HotkeyTableModel extends AbstractTableModel {

		private static final long serialVersionUID = 1L;
		private String[] columns = {
				Translatrix.getTranslationString("Hotkeys.Name"), 
				Translatrix.getTranslationString("Hotkeys.Shortcut"),
				Translatrix.getTranslationString("Hotkeys.HotKey")
		};
		
		private Class[] columnclass = {
				String.class, 
				Integer.class,
				String.class
		};
		
		private Vector<GECAMedAction> actions = new Vector<GECAMedAction>();
		
		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getRowCount()
		 */
		public int getRowCount() {
			return actions.size();
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getColumnCount()
		 */
		public int getColumnCount() {
			return columns.length;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int rowIndex, int columnIndex) {
			
			GECAMedAction a = actions.get(rowIndex);
			
			switch (columnIndex) {
			case 0:
				return a.getTranslatedName();
			case 1:
				return a.getShortcut();
			case 2:
				return a.getHotKey();
			default:
			}
			return null;
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
		 */
		@Override
		public Class<?> getColumnClass(int columnIndex) {
			return columnclass[columnIndex];
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.AbstractTableModel#getColumnName(int)
		 */
		@Override
		public String getColumnName(int column) {
			return columns[column];
		}
		
		/* (non-Javadoc)
		 * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int)
		 */
		@Override
		public boolean isCellEditable(int rowIndex, int columnIndex) {
			if (columnIndex == 0)
				return false;
			else {
				GECAMedAction a = actions.get(rowIndex);
				if (a != null && a.getValue(GECAMedAction.NOT_EDITABLE) != null) {
					return false;					
				} else {
					return true;
				}
			}
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.AbstractTableModel#setValueAt(java.lang.Object, int, int)
		 */
		@Override
		public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
			
			GECAMedAction a = actions.get(rowIndex);
			
			switch (columnIndex) {
			case 0:
				break;
			case 1:
				a.setShortcut((Integer) aValue);
				break;
			case 2:
				a.setHotKey((String) aValue);
				break;
			default:
			}
		}
		
		
		/**
		 * @param actions
		 */
		public void setActions(Vector<GECAMedAction> actions) {
			this.actions = actions;
		}
		
		/**
		 * @return
		 */
		public Vector<GECAMedAction> getActions() {
			return actions;
		}
		
	}
	
	/**
	 * renderer to render the Hotkeys in the JTable
	 * 
	 * @author Johannes Hermen johannes.hermen(at)tudor.lu
	 *
	 * @Version
	 * <br>$Log: HotkeyPanel.java,v $
	 * <br>Revision 1.5  2011-03-04 09:53:11  ferring
	 * <br>Hotkeys for physicians added.
	 * <br>It is now possible to make a hotkey consisting of key + modifiers.
	 * <br>
	 * <br>Revision 1.4  2008-09-25 09:43:07  heinemann
	 * <br>fixed copyrights
	 * <br>
	 * <br>Revision 1.3  2008-01-15 09:29:38  hermen
	 * <br>updated Javadoc and refactured code
	 * <br>
	 * <br>Revision 1.2  2007-12-04 14:59:04  hermen
	 * <br>updated Javadoc and refactured code
	 * <br>
	 *
	 */
	public class HotkeyRenderer extends DefaultTableCellRenderer {
		private static final long serialVersionUID = 1L;
		private boolean isShortcut;
		
		public HotkeyRenderer(final boolean isShortcut)  {
			this.isShortcut = isShortcut;
		}
		
		/* (non-Javadoc)
		 * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
		 */
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			
			String text = "";
			
			if (value instanceof Integer
					&& isShortcut)
			{
				Integer val = (Integer)value;
				if (val.equals(0))
					text = "";
				else 
					text = additionalKey + KeyEvent.getKeyText(val.intValue());
			}
			else
			{
				String val = (String)value;
				if (val == null
						|| val.equals(""))
					text = "";
				else
					text = val;
			}
			
			this.setText(text);
			
//			if ((Integer)value == 0)
//				this.setText("");
//			else 
//				if (isShortcut) {
//					this.setText(additionalKey + KeyEvent.getKeyText((Integer)value));					
//				} else {
//					this.setText((String) value);
//				}
			return this;
		}
		
		
	}
	
	
	/**
	 * editor to edit the Hotkeys in the JTable
	 * 
	 * @author Johannes Hermen johannes.hermen(at)tudor.lu
	 *
	 * @Version
	 * <br>$Log: HotkeyPanel.java,v $
	 * <br>Revision 1.5  2011-03-04 09:53:11  ferring
	 * <br>Hotkeys for physicians added.
	 * <br>It is now possible to make a hotkey consisting of key + modifiers.
	 * <br>
	 * <br>Revision 1.4  2008-09-25 09:43:07  heinemann
	 * <br>fixed copyrights
	 * <br>
	 * <br>Revision 1.3  2008-01-15 09:29:38  hermen
	 * <br>updated Javadoc and refactured code
	 * <br>
	 * <br>Revision 1.2  2007-12-04 14:59:04  hermen
	 * <br>updated Javadoc and refactured code
	 * <br>
	 *
	 */
	public class HotkeyEditor extends AbstractCellEditor implements TableCellEditor {

		private static final long serialVersionUID = 1L;
		private JTextField label;
		private Integer keyCode = 0;
		private String key;
		private boolean isShortcut;

		public HotkeyEditor(final boolean isShortcut)  {
			this.isShortcut = isShortcut;
			this.label = new JTextField();
			this.label.addKeyListener(new KeyAdapter() {
				@Override
				public void keyReleased(KeyEvent e) {
					
					if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
						if (isShortcut)
							keyCode = 0;
						else
							key = "";
					} else {
						if (isShortcut) {
							if (! shortcutExists(e.getKeyCode()))
								keyCode = e.getKeyCode();							
						} else {
							String keyString = GlobalHotkeyRegister.getKeyString(e.getKeyCode(), e.getModifiers());
							if (! hotkeyExists(keyString)) {
//								keyCode = e.getKeyCode();
								key = GlobalHotkeyRegister.getKeyString(e.getKeyCode(), e.getModifiers());
							}
						}
					}
					e.consume();
					fireEditingStopped();
				}
				
			});
		}
		
		/* (non-Javadoc)
		 * @see javax.swing.table.TableCellEditor#getTableCellEditorComponent(javax.swing.JTable, java.lang.Object, boolean, int, int)
		 */
		public Component getTableCellEditorComponent(
	            JTable table, Object value,
	            boolean isSelected, int rowIndex, int colIndex )
	    {
			String text = "";
			
			if (value instanceof Integer
					&& isShortcut)
			{
				Integer val = (Integer)value;
				keyCode = val;
				if (val.equals(0))
					text = "";
				else
					text = additionalKey + KeyEvent.getKeyText(val);
			}
			else if (value instanceof String
					&& !isShortcut)
			{
				String val = (String)value;
				key = val;
				if (val == null
						|| val.equals(""))
					text = "";
				else
					text = val;
			}
			label.setText(text);
			
//			else if (value instanceof String)
//			{
//				key = (String)value;
//			}
//			
//			if ((Integer)value == 0)
//				this.label.setText("");
//			else 
//				if (isShortcut) 
//					this.label.setText(additionalKey + KeyEvent.getKeyText((Integer)value));
//				else
//					this.label.setText(key);		
			return this.label;
	    }
		
		/* (non-Javadoc)
		 * @see javax.swing.CellEditor#getCellEditorValue()
		 */
		public Object getCellEditorValue() {
			if (isShortcut) 
				return keyCode;
			else
				return key;
		}	
	}
	
	/**
	 * check for doubles
	 * @param keyCode
	 * @return
	 */
	private boolean shortcutExists(int keyCode) {
		for (Iterator<GECAMedAction> iter = actions.iterator(); iter.hasNext();) {
			GECAMedAction element = (GECAMedAction) iter.next();
			if (element.getShortcut() == keyCode) {
				Toolkit.getDefaultToolkit().beep();
				return true;
			}
		}
		return false;
	}
	
	/**
	 * check for doubles
	 * @param keyCode
	 * @return
	 */
	private boolean hotkeyExists(String key) {
		for (Iterator iter = actions.iterator(); iter.hasNext();) {
			GECAMedAction element = (GECAMedAction) iter.next();
			if (element.getHotKey() != null && element.getHotKey().equals(key)) {
				Toolkit.getDefaultToolkit().beep();
				return true;
			}
		}
		return false;
	}
	

}
