package lu.tudor.santec.gecamed.formeditor.gui.view.editormenu;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.ComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.IconFetcher;
import lu.tudor.santec.gecamed.core.gui.widgets.LimitTextField;
import lu.tudor.santec.gecamed.core.gui.widgets.NamedComponent;
import lu.tudor.santec.gecamed.formeditor.gui.component.DefaultOptionPanel;
import lu.tudor.santec.gecamed.formeditor.gui.component.EditableComponent;
import lu.tudor.santec.gecamed.formeditor.gui.component.NumericField;
import lu.tudor.santec.gecamed.formeditor.gui.controller.ComponentSettingsController;
import lu.tudor.santec.gecamed.formeditor.gui.model.ComboBoxElement;
import lu.tudor.santec.gecamed.formeditor.gui.model.FormEditorModel;
import lu.tudor.santec.gecamed.formeditor.gui.model.FormModel;
import lu.tudor.santec.i18n.Translatrix;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

public class ComponentSettingsPanel extends MenuSettingsPanel
{
	private static final long serialVersionUID = 1L;
	
	
	/* ======================================== */
	// 		MEMBERS
	/* ======================================== */
	
	
	/* ---------------------------------------- */
	// 		JCOMPONENTS
	/* ---------------------------------------- */
	
	private JButton 			removeComponentBtn;
	private NumericField 		historyIndexField;
	private JTextField 			columnTxt;
	private JTextField 			rowTxt;
	private SpinnerNumberModel 	columnWidthSpnrModel;
	private SpinnerNumberModel 	rowHeightSpnrModel;
	private JLabel 				componentTypeLabel;
	private JTextField 			keyTxt;
	private JCheckBox 			storeInDBBox;
	private JCheckBox 			showInHistory;
	private JTextField 			labelText;
	private JComboBox 			labelPosition;
	private CellConstraints 	additionalOptionsConstraints = new CellConstraints(2, 19, 3, 1);
	private DefaultOptionPanel 	lastAdditonalOptions;
	
	private boolean 			isModifiing = false;
	
	
	
	/* ======================================== */
	// 		CONSTRUCTOR
	/* ======================================== */
	
	public ComponentSettingsPanel(FormEditorModel model)
	{
		super(model);
	}
	
	
	
	/* ======================================== */
	// 		IMPLEMENTED METHODS
	/* ======================================== */
	
	@Override
	protected void initPanel()
	{
		/* **************************************** */
		// 		define the layout
		/* **************************************** */
		
		this.setLayout(new FormLayout("5px, f:75px, 5px, f:75px, 0px",
						"p, 2dlu, " + 	// 1: column 
						"p, 6dlu, " + 	// 3: row 
						"f:p, 2dlu, " + // 5: component-type and remove button
						"p, 2dlu, " + 	// 7: component-key
						"p, 2dlu, " + 	// 9: store in DB
						"p, 2dlu, " + 	// 11: showInHistory-CheckBox
						"p, 2dlu, " + 	// 13: history index
						"p, 2dlu, " + 	// 15: label text
						"p, 2dlu, " + 	// 17: label position
						"p, 0dlu, " + 	// 19: additional options
						"p:g, " + 		// 21: spacer
						"p, 2dlu")); 	// 22: editor, add and remove buttons
		this.setOpaque(false);
		
		CellConstraints cc = new CellConstraints();
		int row = -1;
		

		final ComponentSettingsController settingsController = new ComponentSettingsController(model);
		
		/* **************************************** */
		// 		CURRENT POSITION
		/* **************************************** */
		
		columnTxt = new JTextField();
		columnTxt.setEnabled(false);
		columnTxt.setBackground(MenuSettingsPanel.DISABLED_COLOR);
		
		rowTxt = new JTextField();
		rowTxt.setEnabled(false);
		rowTxt.setBackground(MenuSettingsPanel.DISABLED_COLOR);
		

		/* **************************************** */
		// 		COLUMN- AND ROWSIZE
		/* **************************************** */
		
		columnWidthSpnrModel = new SpinnerNumberModel(1, 1, 1, 1);
		JSpinner columnWidthSpnr = new JSpinner(columnWidthSpnrModel);
		// the spinner model is defined, the maximum column size with the
		// current row size is defined
		columnWidthSpnr.addChangeListener(new ChangeListener()
		{
			public void stateChanged(ChangeEvent e)
			{
				if (!isModifiing())
					settingsController.spinnerChanged((JSpinner)e.getSource(), 
							ComponentSettingsController.CHANGE_COLUMN_WIDTH);
			}
		});

		rowHeightSpnrModel = new SpinnerNumberModel(1, 1, 1, 1);
		JSpinner rowHeightSpnr = new JSpinner(rowHeightSpnrModel);
		
		// the spinner model is defined, the maximum row size with the
		// current column size is defined
		rowHeightSpnr.addChangeListener(new ChangeListener()
		{
			
			public void stateChanged(ChangeEvent e)
			{
				if (!isModifiing())
					settingsController.spinnerChanged((JSpinner)e.getSource(), 
							ComponentSettingsController.CHANGE_ROW_HEIGHT);
			}
		});
		
		
		this.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.column"), 
				columnTxt, true), cc.xy(2, row+=2));
		
		this.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.column_width"),
				columnWidthSpnr, true), cc.xy(4, row));
		
		this.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.row"),
				rowTxt, true), cc.xy(2, row+=2));
		
		this.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.row_height"),
				rowHeightSpnr, true), cc.xy(4, row));
		

		/* **************************************** */
		// 		COMPONENT TYPE AND REMOVE BUTTON
		/* **************************************** */
		
		// 		-- COMPONENT TYPE
		componentTypeLabel = new JLabel();
		componentTypeLabel.setBackground(GECAMedColors.c_GECAMedDarkerBackground);
		componentTypeLabel.setOpaque(true);

		// 		-- REMOVE BUTTON
		removeComponentBtn = new JButton(new AbstractAction("", IconFetcher.getScaledIcon(
				GECAMedModule.class, GECAMedIconNames.REMOVE, 20))
		{
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e)
			{
				settingsController.removeComponent();
			}
		});
		removeComponentBtn.setSize(30, 30);
		removeComponentBtn.setActionCommand(ComponentSettingsController.REMOVE_COMPONENT);
		removeComponentBtn.setToolTipText(
				Translatrix.getTranslationString("formeditor.remove_component"));
		
		removeComponentBtn.addActionListener(new ComponentSettingsController(model));
		
		JPanel p = new JPanel(new FormLayout("f:115px, 5px, c:30px", "f:30px"));
		p.setOpaque(false);
		p.add(componentTypeLabel, cc.xy(1, 1));
		p.add(removeComponentBtn, cc.xy(3, 1));
		this.add(p, cc.xywh(2, row+=2, 3, 1));
		

		/* **************************************** */
		// 		COMPONENT KEY
		/* **************************************** */
		
		keyTxt = new LimitTextField(40);
		keyTxt.addKeyListener(new KeyListener()
		{
			public void keyTyped(KeyEvent e) {}
			public void keyPressed(KeyEvent e) {}
			
			public void keyReleased(KeyEvent e) 
			{
				if (!isModifiing())
					settingsController.setKey(keyTxt);
			}
		});
		
//		new ComponentSettingsController ComponentSettingsController(model,
//				ComponentSettingsController.SET_KEY));
		
		keyTxt.addFocusListener(new FocusListener()
		{
			public void focusLost(FocusEvent e)
			{
				if (!isModifiing())
					settingsController.updateKeys();
			}
			
			public void focusGained(FocusEvent e) {}
		});
//		keyTxt.addFocusListener(new ComponentSettingsController(model,
//				ComponentSettingsController.UPDATE_SCRIPT_EDITOR));
		
		this.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.key"), 
				keyTxt, true), cc.xywh(2, row+=2, 3, 1));
		

		/* **************************************** */
		// 		STORE IN DB
		/* **************************************** */
		
		storeInDBBox = new JCheckBox("<html>"+
				Translatrix.getTranslationString("formeditor.store_in_db"));
		storeInDBBox.setOpaque(false);
		storeInDBBox.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e) 
			{
				if (!isModifiing())
				{
					boolean doStore = ((JCheckBox)e.getSource()).isSelected();
					model.getCurrentlySelectedComponent().setStoreInDB(doStore);
				}
			}
		});
		
		this.add(storeInDBBox, cc.xywh(2, row+=2, 3, 1));
		

		/* **************************************** */
		// 		SHOW IN HISTORY
		/* **************************************** */
		
		showInHistory = new JCheckBox(new AbstractAction("<html><b>" +
				Translatrix.getTranslationString("formeditor.showInHistory") +
				"</b></html>")
		{
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) 
			{
				if (!isModifiing())
				{
					model.getCurrentlySelectedComponent()
							.setShowInHistory(showInHistory.isSelected());
					historyIndexField.setEnabled(showInHistory.isSelected());
				}
			}
		});
		showInHistory.setOpaque(false);
		
		this.add(showInHistory, new CellConstraints(2, row+=2, 3, 1));
		
		
		// 		-- HISTORY INDEX
		
		historyIndexField = new NumericField(0.0f);
//			historyIndexField.setText(curSelComp.getHistoryIndex()+"");
		historyIndexField.setEnabled(showInHistory.isSelected());
		historyIndexField.addCaretListener(new CaretListener() {
			
			public void caretUpdate(CaretEvent e) {
				if (!isModifiing() && model.getCurrentlySelectedComponent() != null)
					model.getCurrentlySelectedComponent().setHistoryIndex(
							(float) ((NumericField)e.getSource()).getDouble());
			}
		});
		
		NamedComponent historyIndexNamedComponent = new NamedComponent(
				Translatrix.getTranslationString("formeditor.historyIndex"), 
				historyIndexField, true, NamedComponent.DIRECTION_HORIZONTAL, NamedComponent.ALIGNMENT_CENTER);
		this.add(historyIndexNamedComponent, cc.xywh(2, row+=2, 3, 1));
		

		/* **************************************** */
		// 		DESCRIPTION
		/* **************************************** */
		
		labelText = new JTextField();
		
		labelText.addCaretListener(new CaretListener() {
			
			public void caretUpdate(CaretEvent e) {
				if (!isModifiing())
				{
					String text = ((JTextField)e.getSource()).getText();
					model.getCurrentlySelectedComponent().setDescription(text);
				}
			}
		});
		
		// define ComboBoxModel:
		Vector<ComboBoxElement<String>> labelPositionModel = new Vector<ComboBoxElement<String>>();
		
		labelPositionModel.addElement(new ComboBoxElement<String>(
				Translatrix.getTranslationString("formeditor.none"),
				FormModel.NONE));
		labelPositionModel.addElement(new ComboBoxElement<String>(
				Translatrix.getTranslationString("formeditor.top"),
				BorderLayout.NORTH));
		labelPositionModel.addElement(new ComboBoxElement<String>(
				Translatrix.getTranslationString("formeditor.right"),
				BorderLayout.EAST));
		labelPositionModel.addElement(new ComboBoxElement<String>(
				Translatrix.getTranslationString("formeditor.bottom"),
				BorderLayout.SOUTH));
		labelPositionModel.addElement(new ComboBoxElement<String>(
				Translatrix.getTranslationString("formeditor.left"),
				BorderLayout.WEST));
		
		labelPosition = new JComboBox(labelPositionModel);
		
		
		// return the selection to the currently selected component
		labelPosition.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e) 
			{
				if (!isModifiing)
				{
					model.getCurrentlySelectedComponent().setDescriptionPosition(
							(String) ((ComboBoxElement<?>)labelPosition.getSelectedItem()).getValue());
					model.getCurrentlySelectedComponent().validate();
				}
			}
		});
		
		this.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.componentDescription"), 
				labelText, true), new CellConstraints(2, row+=2, 3, 1));
		this.add(new NamedComponent(
				Translatrix.getTranslationString("formeditor.componentDescriptionPosition"), 
				labelPosition, true), new CellConstraints(2, row+=2, 3, 1));
		
		
		view.addModifieListener(this);
		/* ================================================== */
	}
	
	
	@Override
	public void preparePanelForSelectedComponent (
			EditableComponent curSelComp)
	{
		try {
			isModifiing = true;
			
			columnTxt.setText(String.valueOf(curSelComp.getColumn() - 1));
			rowTxt.setText(String.valueOf(curSelComp.getRow() - 1));
			
			columnWidthSpnrModel.setValue(curSelComp.getColumnWidth());
			columnWidthSpnrModel.setMaximum(view.getMaxWidthWithCurrentHeight(curSelComp));
			
			rowHeightSpnrModel.setValue(curSelComp.getRowHeight());
			rowHeightSpnrModel.setMaximum(view.getMaxHeightWithCurrentWidth(curSelComp));
			
			componentTypeLabel.setText(new StringBuffer("<html><b><font size=4>")
					.append(curSelComp.getTypeTranslation()) 
					.append(":</font></b></html>")
					.toString());
			
			keyTxt.setText(curSelComp.getKey());
			
			if (curSelComp.isComponentTypeStoredInDBByDefault() == null) 
			{
				storeInDBBox.setEnabled(false);
				storeInDBBox.setSelected(false);
				showInHistory.setEnabled(false);
				showInHistory.setSelected(false);
			} 
			else 
			{
				storeInDBBox.setEnabled(true);
				storeInDBBox.setSelected(curSelComp.isStoredInDB());
				showInHistory.setEnabled(true);
				showInHistory.setSelected(curSelComp.isShowInHistory());
				historyIndexField.setEnabled(curSelComp.isShowInHistory());
			}
			
			historyIndexField.setValue(curSelComp.getHistoryIndex());
			
			labelText.setText(curSelComp.getDescription());
			
			// select the correct item
			String position = curSelComp.getDescriptionPosition();
			ComboBoxModel cbModel = labelPosition.getModel();
			for (int index = 0; index < cbModel.getSize(); index++) 
			{
				ComboBoxElement<?> elem = (ComboBoxElement<?>) cbModel.getElementAt(index);
				if (elem.getValue().equals(position)) 
				{
					labelPosition.setSelectedIndex(index);
					break;
				}
			}
			
			// add additional menu-items by replacing the old ones
			if (lastAdditonalOptions != null)
				this.remove(lastAdditonalOptions);
			lastAdditonalOptions = curSelComp.getOptionPanel();
			this.add(lastAdditonalOptions, additionalOptionsConstraints);
		} finally {
			isModifiing = false;
		}
	}
	
	
	public boolean isModifiing ()
	{
		return isModifiing;
	}
}
