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

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import lu.tudor.santec.gecamed.formeditor.gui.component.EditableComponent;
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.i18n.Translatrix;

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

public class BorderSettingsPanel extends MenuSettingsPanel implements ActionListener, ChangeListener
{
	/* ======================================== */
	// 		STATIC MEMBERS
	/* ======================================== */
	
	private static final String PREFERED_SIZE 	= "p";
	private static final String DEFAULT_SIZE 	= "d";
	private static final String PIXEL_SIZE 		= "px";
	private static final String POINTS_SIZE 	= "pt";
	private static final String INCHES_SIZE 	= "in";
	private static final String MILIMETER_SIZE 	= "mm";
	private static final String CENTIMETER_SIZE = "cm";
	private static final String DLU_SIZE 		= "dlu";

	private static final int INVALID_BORDER = -1;
	private static final int EDGE_BORDER 	= 0;
	private static final int COLUMN_BORDER 	= 1;
	private static final int ROW_BORDER 	= 2;
	
	
	private static final long serialVersionUID = 1L;
	
	public static final int ALIGNMENT 		 = 0;
	public static final int SIZE			 = 1;
	public static final int RESIZE_BEHAVIOUR = 2;
	
	
	/* ---------------------------------------- */
	// 		JCOMPONENTS
	/* ---------------------------------------- */
	
	private ComboBoxModel 	sizeBoxModel;
	private JPanel 			rowSizeSliderPanel;
	private JSlider			rowSizeSlider;
	private JComboBox		rowAlignmentBox;
	private JPanel 			columnSizeSliderPanel;
	private JSlider 		columnSizeSlider;
	private JComboBox		columnAlignmentBox;
	private JComboBox 		resizeComboBox;
//	private JPanel			borderSettingsPanel;
	
	
	
	
	/* ======================================== */
	// 		CONSTRUCTOR
	/* ======================================== */
	
	public BorderSettingsPanel(FormEditorModel model)
	{
		super(model);
	}


	@Override
	protected void initPanel()
	{
		/* **************************************** */
		// 		CREATING THE PANEL
		/* **************************************** */
		CellConstraints 			cc 			= new CellConstraints();
		ComponentSettingsController cbListener 	= new ComponentSettingsController(model);
		
		sizeBoxModel = new DefaultComboBoxModel(new ComboBoxElement<?> [] {
			// elements to define the size
			new ComboBoxElement<String>(Translatrix.getTranslationString("formeditor.unit.pref"), 	PREFERED_SIZE),
			new ComboBoxElement<String>(Translatrix.getTranslationString("formeditor.unit.default"),DEFAULT_SIZE),
			new ComboBoxElement<String>(Translatrix.getTranslationString("formeditor.unit.pixel"), 	PIXEL_SIZE),
			new ComboBoxElement<String>(Translatrix.getTranslationString("formeditor.unit.points"), POINTS_SIZE),
			new ComboBoxElement<String>(Translatrix.getTranslationString("formeditor.unit.inch"), 	INCHES_SIZE),
			new ComboBoxElement<String>(Translatrix.getTranslationString("formeditor.unit.mm"), 	MILIMETER_SIZE),
			new ComboBoxElement<String>(Translatrix.getTranslationString("formeditor.unit.cm"), 	CENTIMETER_SIZE),
			new ComboBoxElement<String>(Translatrix.getTranslationString("formeditor.unit.dlu"), 	DLU_SIZE)
		});
		
		final JComboBox sizeBox = new JComboBox (sizeBoxModel);
		sizeBox.addActionListener(this);
		sizeBox.setOpaque(false);
		
		rowSizeSliderPanel = new JPanel(new FormLayout("f:p, 1px:g, f:p, 15px", "f:p"));
		rowSizeSliderPanel.setOpaque(false);
		
		JLabel sliderTitelLabel = new JLabel(
				Translatrix.getTranslationString("formeditor.row_height") + ":");
		sliderTitelLabel.setOpaque(false);
		rowSizeSliderPanel.add(sliderTitelLabel, cc.xy(1, 1));
		
		final JLabel sliderRowValueLabel = new JLabel(); // String.valueOf(slider.getValue())
		sliderRowValueLabel.setOpaque(false);
		sliderRowValueLabel.setFont(sliderRowValueLabel.getFont().deriveFont(16.0f));
		
		rowSizeSliderPanel.add(sliderRowValueLabel, cc.xy(3, 1));
		
		columnSizeSliderPanel = new JPanel(new FormLayout("f:p, 1px:g, f:p, 15px", "f:p"));
		columnSizeSliderPanel.setOpaque(false);
		
		sliderTitelLabel = new JLabel(
				Translatrix.getTranslationString("formeditor.column_width") + ":");
		sliderTitelLabel.setOpaque(false);
		columnSizeSliderPanel.add(sliderTitelLabel, cc.xy(1, 1));
		
		final JLabel sliderColumnValueLabel = new JLabel(); // String.valueOf(slider.getValue())
		sliderColumnValueLabel.setOpaque(false);
		sliderColumnValueLabel.setFont(sliderColumnValueLabel.getFont().deriveFont(16.0f));
		
		columnSizeSliderPanel.add(sliderColumnValueLabel, cc.xy(3, 1));
		
		
		/*
		 * the resize items are created and put into the comboBox
		 */
		Vector<ComboBoxElement<String>> resizeItems = new Vector<ComboBoxElement<String>>();
		resizeItems.addElement(new ComboBoxElement<String>(
				Translatrix.getTranslationString("formeditor.none"),
				"none", String.valueOf(RESIZE_BEHAVIOUR)));
		resizeItems.addElement(new ComboBoxElement<String>(
				Translatrix.getTranslationString("formeditor.grow"),
				"grow", String.valueOf(RESIZE_BEHAVIOUR)));
		resizeComboBox = new JComboBox(resizeItems);
		resizeComboBox.addItemListener(cbListener);
		resizeComboBox.setActionCommand(ComponentSettingsController.FORMAT_CELLS);
		
		
		/* **************************************** */
		// 		DEFINE THE ROW SETTINGS
		/* **************************************** */
		
		// a row is selected
		rowSizeSlider = new JSlider(0, 400, 0);
//		borderSettingsRowSizeSlider = new JSlider(0, 400, Integer
//				.parseInt(getFormLayoutRowDefinition(
//						curSelComp.getRow()).split(":")[1].replace(
//								"px", "")));
//		rowSizeSlider.addChangeListener(new MenuPanelController(model,
//				MenuPanelController.CHANGE_HEIGHT));
		rowSizeSlider.addChangeListener(this);
		
		rowSizeSlider.setOpaque(false);
		rowSizeSlider.setMajorTickSpacing(100);
		rowSizeSlider.setPaintTicks(true);
		rowSizeSlider.setPaintLabels(true);
		
		rowSizeSlider.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				/* ---------------------------------------- */
				sliderRowValueLabel.setText(String.valueOf(
						((JSlider)e.getSource()).getValue()));
				/* ---------------------------------------- */
			}
		});
		
		
		Vector<ComboBoxElement<Object>> alignmentItems = new Vector<ComboBoxElement<Object>>();
		
		// the alignment items are created and put into the comboBox
		alignmentItems.addElement(new ComboBoxElement<Object>(
				Translatrix.getTranslationString("formeditor.top"), 
				"top", ALIGNMENT));
		alignmentItems.addElement(new ComboBoxElement<Object>(
				Translatrix.getTranslationString("formeditor.center"), 
				"center", ALIGNMENT));
		alignmentItems.addElement(new ComboBoxElement<Object>(
				Translatrix.getTranslationString("formeditor.bottom"), 
				"bottom", ALIGNMENT));
		alignmentItems.addElement(new ComboBoxElement<Object>(
				Translatrix.getTranslationString("formeditor.fill"), 
				"fill", ALIGNMENT));
		
		rowAlignmentBox = new JComboBox(alignmentItems);
		
		rowAlignmentBox.addItemListener(cbListener);
		rowAlignmentBox.setActionCommand(ComponentSettingsController.FORMAT_CELLS);

		
		
		/* **************************************** */
		// 		DEFINE THE COLUMN SETTINGS
		/* **************************************** */

		// a column is selected
		columnSizeSlider = new JSlider(0, 400, 0);
//		borderSettingsColumnSizeSlider = new JSlider(0, 400, Integer
//				.parseInt(getFormLayoutColDefinition(
//						curSelComp.getColumn()).split(":")[1].replace(
//						"px", "")));
//		columnSizeSlider.addChangeListener(new MenuPanelController(model,
//				MenuPanelController.CHANGE_WIDTH));
		columnSizeSlider.addChangeListener(this);
		
		columnSizeSlider.setOpaque(false);
		columnSizeSlider.setMajorTickSpacing(100);
		columnSizeSlider.setPaintTicks(true);
		columnSizeSlider.setPaintLabels(true);
		
		columnSizeSlider.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				/* ---------------------------------------- */
				sliderColumnValueLabel.setText(String.valueOf(
						((JSlider)e.getSource()).getValue()));
				/* ---------------------------------------- */
			}
		});
		
		
		// the alignment items are created and put into the comboBox
		alignmentItems = new Vector<ComboBoxElement<Object>>();
		alignmentItems.addElement(new ComboBoxElement<Object>(
				Translatrix.getTranslationString("formeditor.left"), 
				"left", ALIGNMENT));
		alignmentItems.addElement(new ComboBoxElement<Object>(
				Translatrix.getTranslationString("formeditor.center"), 
				"center", ALIGNMENT));
		alignmentItems.addElement(new ComboBoxElement<Object>(
				Translatrix.getTranslationString("formeditor.right"), 
				"right", ALIGNMENT));
		alignmentItems.addElement(new ComboBoxElement<Object>(
				Translatrix.getTranslationString("formeditor.fill"), 
				"fill", ALIGNMENT));
		
		columnAlignmentBox = new JComboBox(alignmentItems);
		columnAlignmentBox.addItemListener(cbListener);
		columnAlignmentBox.setActionCommand(ComponentSettingsController.FORMAT_CELLS);
		
		
		/* **************************************** */
		// 		CREATE THE PANEL
		/* **************************************** */
		
		this.setLayout(new FormLayout("5px, 155px, 0px", 
				"p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p:g, p, 2dlu"));
		this.setOpaque(false);
		
		int index = -1;
		
//		settingsPnl.setLayout(new FormLayout(,
//						"p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p:g, p, 2dlu"));
		this.add(sizeBox,				cc.xy(2, index+=2));
		this.add(columnSizeSliderPanel, cc.xy(2, index+=2));
		this.add(rowSizeSliderPanel, 	cc.xy(2, index+=2));
		
		this.add(columnSizeSlider, 		cc.xy(2, index+=2));
		this.add(rowSizeSlider, 		cc.xy(2, index+=2));
		
		this.add(new JLabel(
				Translatrix.getTranslationString("formeditor.alignment")+ ":"), 
										cc.xy(2, index+=2));
		
		this.add(columnAlignmentBox, 	cc.xy(2, index+=2));
		this.add(rowAlignmentBox, 		cc.xy(2, index+=2));
		
		this.add(new JLabel(
				Translatrix.getTranslationString("formeditor.resize_behaviour")+ ":"),
										cc.xy(2, index+=2));
		this.add(resizeComboBox, 		cc.xy(2, index+=2));
		
		view.addModifieListener(this);
		
		// END: CREATING THE PANEL
	}
	
	
	
	/* ======================================== */
	// 		IMPLEMENTED METHODS
	/* ======================================== */
	
	public void preparePanelForSelectedComponent (EditableComponent curSelComp)
	{
		int orientation = getOrientation(curSelComp);
		
		if (orientation == EDGE_BORDER
				|| orientation == INVALID_BORDER)
			return;
		
		DefaultComboBoxModel alignmentItems;
		String[] definition;
		JSlider slider;
		

		/* **************************************** */
		// 		ACTIVATE THE RIGHT PANELS
		/* **************************************** */
		
		boolean showRowComponents = orientation == ROW_BORDER;
		
		// a row is selected
		rowAlignmentBox.setVisible(showRowComponents);
		rowSizeSlider.setVisible(showRowComponents);

		columnAlignmentBox.setVisible(!showRowComponents);
		columnSizeSlider.setVisible(!showRowComponents);
		
		rowSizeSliderPanel.setVisible(showRowComponents);
		columnSizeSliderPanel.setVisible(!showRowComponents);
		
		if (showRowComponents)
		{
			alignmentItems = (DefaultComboBoxModel)rowAlignmentBox.getModel();
			definition = view.getFormLayoutRowDefinition(curSelComp.getRow()).split(":");
			slider = rowSizeSlider;
		}
		else
		{
			alignmentItems = (DefaultComboBoxModel)columnAlignmentBox.getModel();
			definition = view.getFormLayoutColDefinition(curSelComp.getColumn()).split(":");
			slider = columnSizeSlider;
		}
		

		/* **************************************** */
		// 		SET THE SLIDER VALUE
		/* **************************************** */
		
		int value;
		try 
		{
			value = Integer.parseInt(definition[1].replaceAll("\\D", ""));
		} 
		catch (NumberFormatException e) 
		{
			value = orientation == COLUMN_BORDER ? curSelComp.getWidth() : curSelComp.getHeight();
		}
		slider.setValue(value);


		/* **************************************** */
		// 		SET THE COMBOBOX VALUES
		/* **************************************** */
		
		DefaultComboBoxModel resizeItems = (DefaultComboBoxModel) resizeComboBox.getModel();
		
		// alignment box
		chooseComboBoxElement(alignmentItems, definition[ALIGNMENT]);
		
		// resize box
		chooseComboBoxElement(resizeItems, definition[RESIZE_BEHAVIOUR]);
		
		// size box
		chooseComboBoxElement(sizeBoxModel, getSizeComparable(definition[SIZE]));
	}


	public void stateChanged(ChangeEvent e)
	{
		setLayoutDefinition();
	}


	public void actionPerformed(ActionEvent e)
	{
		JComboBox box 			= ((JComboBox)			e.getSource());
		ComboBoxElement<?> item = (ComboBoxElement<?>) 	box.getSelectedItem();
		String unit 			= (String) 				item.getValue();
		boolean enabled = !unit.equals(PREFERED_SIZE)
						&& !unit.equals(DEFAULT_SIZE);
		columnSizeSlider.setEnabled(enabled);
		rowSizeSlider.setEnabled(enabled);
		
		setLayoutDefinition();
	}
	
	
	
	/* ======================================== */
	// 		HELP METHODS
	/* ======================================== */

	private String getSizeComparable(String unit)
	{
		unit = unit.replaceAll("\\d", "").toLowerCase();
		
		if (	   unit.equals("p") 
				|| unit.equals("pref") 
				|| unit.equals("prefered"))
			unit = PREFERED_SIZE;
		else if (unit.equals("d")
				|| unit.equals("def")
				|| unit.equals("default"))
			unit = DEFAULT_SIZE;
		else if (unit.equals(""))
			unit = PIXEL_SIZE;
		
		return unit;
	}
	
	
	private int getOrientation (EditableComponent component)
	{
		int col = component.getColumn();
		int row = component.getRow();
		
		if (col == 1 && row == 1)
			return EDGE_BORDER;
		else if (col == 1)
			return ROW_BORDER;
		else if (row == 1)
			return COLUMN_BORDER;
		else
			return INVALID_BORDER;
	}
	
	
	private void setLayoutDefinition ()
	{
		int orientation 		= getOrientation(model.getCurrentlySelectedComponent());
		EditableComponent ec 	= model.getCurrentlySelectedComponent();
		String definition;
		
		if (orientation == COLUMN_BORDER)
		{
			definition 			= view.getFormLayoutColDefinition(ec.getColumn());
			definition 			= defineLayout(definition, columnSizeSlider);
			view.setFormLayoutColDefinition(ec.getColumn(), definition);
		}
		else if (orientation == ROW_BORDER)
		{
			// a row is selected, the height has to be fit
			definition 			= view.getFormLayoutRowDefinition(ec.getRow());
			definition 			= defineLayout(definition, rowSizeSlider);
			view.setFormLayoutRowDefinition(ec.getRow(), definition);
		} 
		else
			return;
		
		view.rearrangeEditPanel();
	}
	
	
	private String defineLayout (String oldDefinition, JSlider slider)
	{
		String newDefinition;
		ComboBoxElement<?> item = (ComboBoxElement<?>) sizeBoxModel.getSelectedItem();
		String unit 			= (String) item.getValue();
		String[] defArray 		= oldDefinition.split(":");
		
		String sliderValue;
		if (PREFERED_SIZE.equals(unit)
				|| DEFAULT_SIZE.equals(unit))
			sliderValue 		= "";
		else
			sliderValue 		= String.valueOf(slider.getValue());
		
		newDefinition 			= new StringBuffer(defArray[0])
											.append(":")
											.append(sliderValue)
											.append(unit)
											.append(":")
											.append(defArray[2])
											.toString();
		
		return newDefinition;
	}
	
	
	private void chooseComboBoxElement (ComboBoxModel model, String compareTo)
	{
		ComboBoxElement<?> cbe;
		for (int i = 0; i < model.getSize(); i++) 
		{
			cbe = (ComboBoxElement<?>) model.getElementAt(i);
			if (cbe.getValue().equals(compareTo))
			{
				model.setSelectedItem(cbe);
				break;
			}
		}
	}
}
