//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010 huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/god4j
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : god4j@lists.sourceforge.net 
 */
//----------------------------END  LICENSE-----------------------------
package org.huihoo.god4j.editor.panels;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.huihoo.god4j.editor.XPDLCollection;
import org.huihoo.god4j.editor.XPDLComplexComponent;
import org.huihoo.god4j.editor.XPDLComponent;
import org.huihoo.god4j.editor.JavaDialog;
import org.huihoo.god4j.util.ImageLoader;
/**
 * @author reic
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public class JavaListPanel extends JavaPanel
{
	private static Dimension minimalDimension = new Dimension(250, 60);
	private static Dimension listDimension = new Dimension(250, 100);
	/**
		* Object which we are replacing from one place to another within
		* the list by draging it.
		*/
	private Object replacingObject;
	/**
		* Index of the object which we are replacing from one place to another
		* within the list by draging it.
		*/
	private int startReplaceIndex;
	/**
		* The new index of the object which we are replacing from one place
		* to another within the list by draging it.
		*/
	private int endReplaceIndex;
	/** Indicates if object is beeing draged. */
	private boolean dragging = false;
	/**
		* Indicates if the code for changing object position within the list
		* is executed.
		*/
	private boolean changing = false;
	public JavaListPanel(XPDLCollection myOwner, String title, boolean hasBorder, final boolean enableEditing, boolean minDimension)
	{
		super(myOwner, 2, title, JavaPanel.BOX_LAYOUT, false, hasBorder);
		JScrollPane scrollParam = new JScrollPane();
		scrollParam.setAlignmentX(Component.LEFT_ALIGNMENT);
		//scrollParam.setAlignmentY(Component.TOP_ALIGNMENT);
		final DefaultListModel listModel = new DefaultListModel();
		// fills list
		Iterator it = myOwner.toCollection().iterator();
		while (it.hasNext())
		{
			XPDLComponent elem = (XPDLComponent) it.next();
			//System.err.println("--------LIST------>"+elem);
			listModel.addElement(elem);
		}
		final JList allParam = new JList(listModel);
		allParam.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		allParam.setAlignmentX(Component.LEFT_ALIGNMENT);
		allParam.setAlignmentY(Component.TOP_ALIGNMENT);
		// mouse listener for editing on double-click and dragging list items
		allParam.addMouseListener(new MouseAdapter()
		{
			public void mouseClicked(MouseEvent me)
			{
				// implement some action only if editing is enabled
				if (enableEditing && me.getClickCount() > 1)
				{
					editElementDialog();
				}
			}
			/** Marks the object which place within the list will be changed.*/
			public void mousePressed(MouseEvent me)
			{
				if (getXPDLComponent().isReadOnly())
					return;
				dragging = true;
				JList l = getList();
				replacingObject = null;
				startReplaceIndex = -1;
				try
				{
					replacingObject = l.getSelectedValue();
					startReplaceIndex = l.getSelectedIndex();
				}
				catch (Exception ex)
				{
				}
			}
			/** Just indicates that dragging is over.*/
			public void mouseReleased(MouseEvent me)
			{
				dragging = false;
			}
		});
		/** Changes position of object within the list.*/
		if (!myOwner.isReadOnly())
		{
			allParam.addListSelectionListener(new ListSelectionListener()
			{
				public void valueChanged(ListSelectionEvent lse)
				{
					if (dragging && !changing)
					{
						changing = true;
						JList l = (JList) lse.getSource();
						endReplaceIndex = -1;
						try
						{
							endReplaceIndex = l.getSelectedIndex();
						}
						catch (Exception ex)
						{
						}
						if (replacingObject == null || startReplaceIndex == -1 || endReplaceIndex == -1 || startReplaceIndex == endReplaceIndex)
						{
							changing = false;
							return;
						}
						DefaultListModel listModel = (DefaultListModel) l.getModel();
						listModel.remove(startReplaceIndex);
						listModel.add(endReplaceIndex, replacingObject);
						((XPDLCollection) getXPDLComponent()).removeComponent(replacingObject);
						((ArrayList) ((XPDLCollection) getXPDLComponent()).toCollection()).add(endReplaceIndex, replacingObject);
						try
						{
							l.setSelectedIndex(endReplaceIndex);
						}
						catch (Exception ex)
						{
						}
						if (startReplaceIndex != endReplaceIndex)
						{
							//((XPDLCompDialog) getDialog()).notifyListeners(getOwner());
						}
						startReplaceIndex = endReplaceIndex;
						changing = false;
					}
				}
			});
			allParam.setToolTipText(sm.getString("MessageDragItemToChangeItsPosition"));
		}
		if (enableEditing)
		{
			allParam.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "edit");
			allParam.getActionMap().put("edit", new AbstractAction()
			{
				public void actionPerformed(ActionEvent e)
				{
					editElementDialog();
				}
			});
			allParam.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false), "delete");
			allParam.getActionMap().put("delete", new AbstractAction()
			{
				public void actionPerformed(ActionEvent e)
				{
					removeSelectedElement();
				}
			});
		}
		scrollParam.setViewportView(allParam);
		if (!minDimension)
		{
			scrollParam.setPreferredSize(new Dimension(listDimension));
		}
		else
		{
			scrollParam.setPreferredSize(new Dimension(minimalDimension));
		}
		add(scrollParam);
		JPanel p = new JPanel();
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
		JButton buttonUp = new JButton();
		ImageIcon imgIcon=ImageLoader.getImageIcon(ImageLoader.getImageName("ArrowUpImage"));
		if (imgIcon != null)
		{
			buttonUp.setIcon(imgIcon);
		}
		buttonUp.setEnabled(!myOwner.isReadOnly());
		buttonUp.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				moveItem(0);
			}
		});
		buttonUp.setPreferredSize(new Dimension(25, 25));
		JButton buttonDown = new JButton();
		imgIcon=ImageLoader.getImageIcon(ImageLoader.getImageName("ArrowDownImage"));
		if (imgIcon != null)
		{
			buttonDown.setIcon(imgIcon);
		}

		buttonDown.setEnabled(!myOwner.isReadOnly());
		buttonDown.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				moveItem(1);
			}
		});
		buttonDown.setPreferredSize(new Dimension(25, 25));
		p.add(buttonUp);
		p.add(Box.createVerticalGlue());
		p.add(buttonDown);
		add(Box.createRigidArea(new Dimension(5, 0)));
		add(p);
	}
	public boolean isItemChangingPosition()
	{
		return (changing || dragging);
	}
	public JList getList()
	{
		JScrollPane jsp = (JScrollPane) getComponent(0);
		JViewport jvp = (JViewport) jsp.getComponent(0);
		JList l = (JList) jvp.getComponent(0);
		return l;
	}
	private void editElementDialog()
	{
		XPDLComponent editElement = null;
		try
		{
			editElement = (XPDLComponent) getList().getSelectedValue();
		}
		catch (Exception ex)
		{
		}
		if (editElement != null)
		{
			JavaDialog de =
				new JavaDialog((JDialog) getDialog(), editElement.getLabel() + " '" + editElement.toString() + "' - " + sm.getString("EditingKey"));
			de.editXPDLComponent(editElement.getJavaPanel(), true, false);
			if (!de.isCanceled())
			{
				((XPDLCollection) getXPDLComponent()).onElementModified(editElement);
				paintAll(getGraphics());
			}
		}
		else
		{
			JOptionPane.showMessageDialog(
				getDialog(),
				sm.getString("WarningEmptySelectionToEditOrDelete"),
				sm.getString("Title"),
				JOptionPane.WARNING_MESSAGE);
		}
		getList().requestFocus();
	}
	private void removeSelectedElement()
	{
		JList l = getList();
		Object obj = null;
		int ind = 0;
		try
		{
			obj = l.getSelectedValue();
			ind = l.getSelectedIndex();
		}
		catch (Exception ex)
		{
		}
		if (obj != null)
		{
			if (((XPDLCollection) getXPDLComponent()).canRemoveElement((XPDLComponent) obj))
			{
				int yn =
					JOptionPane.showConfirmDialog(
						getDialog(),
						sm.getString("MessageDoYouReallyWantToRemoveSelectedItem"),
						((XPDLComponent) obj).getLabel() + " - " + sm.getString("DeletingKey"),
						JOptionPane.YES_NO_OPTION);
				if (yn == JOptionPane.YES_OPTION)
				{
					DefaultListModel listModel = (DefaultListModel) l.getModel();
					listModel.removeElement(obj);
					((XPDLCollection) getXPDLComponent()).removeComponent(obj);
					((XPDLCollection) getXPDLComponent()).onElementRemoved((XPDLComponent) obj);
				}
				else
				{
					l.requestFocus();
					return;
				}
			}
			else
			{
				String message = "";
				if (obj instanceof XPDLComplexComponent)
				{
					message = sm.getString(((XPDLCollection) getXPDLComponent()).getInUseMessageName((XPDLComplexComponent) obj));
				}
				JOptionPane.showMessageDialog(getDialog(), message, sm.getString("Title"), JOptionPane.ERROR_MESSAGE);
			}
		}
		else
		{
			JOptionPane.showMessageDialog(
				getDialog(),
				sm.getString("WarningEmptySelectionToEditOrDelete"),
				sm.getString("Title"),
				JOptionPane.WARNING_MESSAGE);
		}
		try
		{
			if (ind == 0)
			{
				ind++;
			}
			l.setSelectedIndex(ind - 1);
		}
		catch (Exception ex)
		{
		}
		l.requestFocus();
	}
	private void moveItem(int upOrDown)
	{
		changing = true;
		JList l = getList();
		Object rObject = null;
		int sri = -1;
		try
		{
			rObject = l.getSelectedValue();
			sri = l.getSelectedIndex();
		}
		catch (Exception ex)
		{
		}
		if (rObject == null || sri == -1)
		{
			changing = false;
			return;
		}
		int eri = sri;
		if (upOrDown == 0)
		{
			eri--;
		}
		else
		{
			eri++;
		}
		if (eri < 0)
		{
			eri = 0;
		}
		if (eri > ((XPDLCollection) getXPDLComponent()).size() - 1)
		{
			eri = ((XPDLCollection) getXPDLComponent()).size() - 1;
		}
		DefaultListModel listModel = (DefaultListModel) l.getModel();
		listModel.remove(sri);
		listModel.add(eri, rObject);
		((XPDLCollection) getXPDLComponent()).removeComponent(rObject);
		((ArrayList) ((XPDLCollection) getXPDLComponent()).toCollection()).add(eri, rObject);
		try
		{
			l.setSelectedIndex(eri);
		}
		catch (Exception ex)
		{
		}
		if (sri != eri)
		{
			//((XPDLCompDialog) getDialog()).notifyListeners(getOwner());
		}
		changing = false;
	}
	
	public void applyChanges()
	{
	}
}