//----------------------------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.tree;
//import org.huihoo.workflow.xpdl.businessfunction.*;
import java.awt.Point;

import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

import org.huihoo.god4j.GOD4JConstants;
import org.huihoo.god4j.GOD4JFactory;
import org.huihoo.god4j.JGraphFrame;
import org.huihoo.god4j.actions.ActionBase;
import org.huihoo.god4j.actions.ShowGraph;
import org.huihoo.god4j.editor.JavaDialog;
import org.huihoo.god4j.editor.elements.XPDLActivity;
import org.huihoo.god4j.editor.elements.XPDLApplication;
import org.huihoo.god4j.editor.elements.XPDLDataField;
import org.huihoo.god4j.editor.elements.XPDLPackage;
import org.huihoo.god4j.editor.elements.XPDLProcess;
import org.huihoo.god4j.editor.elements.XPDLTransition;
import org.huihoo.god4j.editor.elements.set.XPDLActivities;
import org.huihoo.god4j.editor.elements.set.XPDLApplications;
import org.huihoo.god4j.editor.elements.set.XPDLDataFields;
import org.huihoo.god4j.editor.elements.set.XPDLProcesses;
import org.huihoo.god4j.editor.elements.set.XPDLTransitions;
import org.huihoo.god4j.jgraph.XPDLJGraph;
import org.huihoo.god4j.util.BarFactory;
import org.huihoo.god4j.util.StringManager;
import org.huihoo.workflow.xpdl.WorkflowActivity;
import org.huihoo.workflow.xpdl.WorkflowApplication;
import org.huihoo.workflow.xpdl.WorkflowPackage;
import org.huihoo.workflow.xpdl.WorkflowParameter;
import org.huihoo.workflow.xpdl.WorkflowProcess;
import org.huihoo.workflow.xpdl.WorkflowTransition;
import org.huihoo.workflow.xpdl.activity.ActivityType;

public class NodeExplorer extends JTree
{
	private static StringManager sm_god4j = StringManager.getManager(GOD4JConstants.PACKAGE);
	private static StringManager sm_tree = StringManager.getManager(ExplorerConstants.PACKAGE);

	private NodeExplorerModel treeModel = null;

	public NodeExplorer()
	{
		this.treeModel = new NodeExplorerModel(this);
		this.setModel(treeModel);

		this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		this.addTreeSelectionListener(new NodeExplorerSelectionListener(this));

		this.addMouseListener(new NodeExplorerMouseListner(this));
		this.setCellRenderer(new NodeExplorerRenderer());

		this.setToggleClickCount(1);
		this.setFont(GOD4JConstants.WINDOWS_UI_FONT);
	}

	//----------------------------------------------------------------------------------------------
	public void setSelectionNode(String objUUID)
	{
		treeModel.setSelectionNode(objUUID);
	}

	//----------------------------------------------------------------------------------------------
	public void loadDocument()
	{
		treeModel.loadDocument();
	}

	public void graphDelete()
	{
		ExplorerNode treeNode = (ExplorerNode) this.getLastSelectedPathComponent();

		if (ExplorerUtilities.isNullNode(treeNode))
		{
			return;
		}

		if (ExplorerUtilities.isParameterNode(treeNode))
		{
			WorkflowParameter param_remove = (WorkflowParameter) treeNode.getWorkflowComponent();
			WorkflowPackage pkg_def = GOD4JFactory.getGOD4J().getDocument();
			if (!ExplorerUtilities.canRemoveWorkflowParameter(pkg_def, param_remove))
			{
				JOptionPane.showMessageDialog(
					GOD4JFactory.getGOD4J(),
					sm_tree.getString("joptionpane.warnCannotDeleteWorkflowRelevantDataThatIsInUse"),
					sm_tree.getString("joptionpane.warn"),
					JOptionPane.YES_OPTION);
				return;
			}

			GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().removeWorkflowParameter(param_remove);
			pkg_def.removeWorkflowParameter(param_remove);

			GOD4JFactory.getGOD4J().setDirty(true);
			GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().updateUI();
		}
		else if (ExplorerUtilities.isApplicationNode(treeNode))
		{
			WorkflowApplication app_remove = (WorkflowApplication) treeNode.getWorkflowComponent();
			WorkflowPackage pkg_def = GOD4JFactory.getGOD4J().getDocument();
			if (!ExplorerUtilities.canRemoveWorkflowApplication(pkg_def, app_remove))
			{
				JOptionPane.showMessageDialog(
					GOD4JFactory.getGOD4J(),
					sm_tree.getString("joptionpane.warnCannotDeleteApplicationThatIsInUse"),
					sm_tree.getString("joptionpane.warn"),
					JOptionPane.YES_OPTION);
				return;
			}

			GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().removeWorkflowApplication(app_remove);
			pkg_def.removeWorkflowApplication(app_remove);

			GOD4JFactory.getGOD4J().setDirty(true);
			GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().updateUI();
		}
		else if (ExplorerUtilities.isProcessNode(treeNode))
		{
			WorkflowProcess proc_remove = (WorkflowProcess) treeNode.getWorkflowComponent();

			WorkflowProcessNodeObject processObject = treeModel.findWorkflowProcessNodeObject(proc_remove.getUUID());
			if (!processObject.isChildProcess())
			{
				JOptionPane.showMessageDialog(
					GOD4JFactory.getGOD4J(),
					sm_tree.getString("joptionpane.warnCannotDeleteProcessThatIsMainProcess"),
					sm_tree.getString("joptionpane.warn"),
					JOptionPane.YES_OPTION);
				return;
			}

			WorkflowPackage pkg_def = GOD4JFactory.getGOD4J().getDocument();
			if (!ExplorerUtilities.canRemoveWorkflowProcess(pkg_def, proc_remove))
			{
				JOptionPane.showMessageDialog(
					GOD4JFactory.getGOD4J(),
					sm_tree.getString("joptionpane.warnCannotDeleteProcessThatIsInUseBySomeSubflowActivity"),
					sm_tree.getString("joptionpane.warn"),
					JOptionPane.YES_OPTION);
				return;
			}

			GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().removeWorkflowProcess(proc_remove);
			GOD4JFactory.getGOD4J().getControlPanel().removeJGraph(proc_remove.getUUID());
			pkg_def.removeWorkflowProcess(proc_remove);

			GOD4JFactory.getGOD4J().setDirty(true);
			GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().repaint();
		}
		else if (ExplorerUtilities.isActivityNode(treeNode) || ExplorerUtilities.isTransitionNode(treeNode))
		{
			JGraphFrame frame = GOD4JFactory.getGOD4J().getControlPanel().getSelectedJGraph();
			if (frame == null)
			{
				if (ExplorerUtilities.isActivityNode(treeNode))
				{
					WorkflowActivity act = (WorkflowActivity) treeNode.getWorkflowComponent();
					frame = GOD4JFactory.getGOD4J().getControlPanel().findJGraph(act.getWorkflowProcess().getUUID());
					GOD4JFactory.getGOD4J().getControlPanel().setSelectedJGraph(frame);
				}
				else if (ExplorerUtilities.isTransitionNode(treeNode))
				{
					WorkflowTransition trans = (WorkflowTransition) treeNode.getWorkflowComponent();
					frame = GOD4JFactory.getGOD4J().getControlPanel().findJGraph(trans.getWorkflowProcess().getUUID());
					GOD4JFactory.getGOD4J().getControlPanel().setSelectedJGraph(frame);
				}
			}
			if (frame != null)
			{
				XPDLJGraph jGraph = frame.getJGraph();
				jGraph.graphDelete();
			}
		}

	}

	public void graphProperties()
	{
		ExplorerNode treeNode = (ExplorerNode) this.getLastSelectedPathComponent();
		if (ExplorerUtilities.isNullNode(treeNode))
		{
			return;
		}
		
		if (ExplorerUtilities.isPackageNode(treeNode))
		{
			XPDLPackage xpdlPackage = GOD4JFactory.getGOD4J().getXPDLDocument();

			JavaDialog dlg = new JavaDialog(GOD4JFactory.getGOD4J(),"");
			dlg.editXPDLComponent(xpdlPackage.getJavaPanel(), true, false);
			if (!dlg.isCanceled())
			{
				GOD4JFactory.getGOD4J().setDirty(true);
				GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().updateUI();
			}
		}
		else if (ExplorerUtilities.isParameterNode(treeNode))
		{
			WorkflowParameter workflowParameter = (WorkflowParameter) treeNode.getWorkflowComponent();

			XPDLPackage xpdlPackage = GOD4JFactory.getGOD4J().getXPDLDocument();
			xpdlPackage.loadComponent();

			XPDLDataFields xpdlDataFields = (XPDLDataFields) xpdlPackage.get("DataFields");
			XPDLDataField xpdlDataField = (XPDLDataField) xpdlDataFields.findComponent(workflowParameter.getUUID());

			JavaDialog dlg = new JavaDialog(GOD4JFactory.getGOD4J(),"");
			dlg.editXPDLComponent(xpdlDataField.getJavaPanel(), true, false);
			if (!dlg.isCanceled())
			{
				GOD4JFactory.getGOD4J().setDirty(true);
				GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().updateUI();
			}
		}
		else if (ExplorerUtilities.isApplicationNode(treeNode))
		{
			WorkflowApplication workflowApplication = (WorkflowApplication) treeNode.getWorkflowComponent();

			XPDLPackage xpdlPackage = GOD4JFactory.getGOD4J().getXPDLDocument();
			xpdlPackage.loadComponent();

			XPDLApplications xpdl_apps = (XPDLApplications) xpdlPackage.get("Applications");
			XPDLApplication xpdl_app = (XPDLApplication) xpdl_apps.findComponent(workflowApplication.getUUID());

			JavaDialog dlg = new JavaDialog(GOD4JFactory.getGOD4J(),"");
			dlg.editXPDLComponent(xpdl_app.getJavaPanel(), true, false);
			if (!dlg.isCanceled() && !xpdl_app.isReadOnly())
			{
				GOD4JFactory.getGOD4J().setDirty(true);
				GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().updateUI();
			}
		}
		else if (ExplorerUtilities.isProcessNode(treeNode))
		{
			WorkflowProcess workflowProcess = (WorkflowProcess) treeNode.getWorkflowComponent();

			XPDLPackage xpdlPackage = GOD4JFactory.getGOD4J().getXPDLDocument();
			xpdlPackage.loadComponent();

			XPDLProcesses xpdl_processes = (XPDLProcesses) xpdlPackage.get("WorkflowProcesses");
			xpdl_processes.loadComponent();
			XPDLProcess xpdl_process = (XPDLProcess) xpdl_processes.findComponent(workflowProcess.getUUID());

			JavaDialog dlg = new JavaDialog(GOD4JFactory.getGOD4J(),"");
			dlg.editXPDLComponent(xpdl_process.getJavaPanel(), true, false);
			if (!dlg.isCanceled() && !xpdl_process.isReadOnly())
			{
				GOD4JFactory.getGOD4J().setDirty(true);
				JGraphFrame graphFrame = GOD4JFactory.getGOD4J().getControlPanel().findJGraph(workflowProcess.getUUID());
				graphFrame.setTitle(workflowProcess.getName());

				GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().updateUI();
			}
		}
		else if (ExplorerUtilities.isActivityNode(treeNode))
		{
			XPDLPackage xpdlPackage = GOD4JFactory.getGOD4J().getXPDLDocument();
			xpdlPackage.loadComponent();

			WorkflowActivity act = (WorkflowActivity) treeNode.getWorkflowComponent();
			WorkflowProcess workflowProcess = act.getWorkflowProcess();
			XPDLProcesses xpdl_processes = (XPDLProcesses) xpdlPackage.get("WorkflowProcesses");
			xpdl_processes.loadComponent();

			XPDLProcess xpdl_process = (XPDLProcess) xpdl_processes.findComponent(workflowProcess.getUUID());
			xpdl_process.loadComponent();

			XPDLActivities xpdl_acts = (XPDLActivities) xpdl_process.get("Activities");
			xpdl_acts.loadComponent();

			XPDLActivity xpdl_act = (XPDLActivity) xpdl_acts.findComponent(act.getUUID());
			xpdl_act.loadComponent();

			if (ActivityType.ACTIVITY_BEGIN.equals(act.getActivityType())
				|| ActivityType.ACTIVITY_END.equals(act.getActivityType()))
			{
				xpdl_act.setReadOnly(true);
			}

			JavaDialog dlg = new JavaDialog(GOD4JFactory.getGOD4J(),"");
			dlg.editXPDLComponent(xpdl_act.getJavaPanel(), true, false);
			if (!dlg.isCanceled() && !xpdl_act.isReadOnly())
			{
				GOD4JFactory.getGOD4J().setDirty(true);
				GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().updateUI();
			}
		}
		else if (ExplorerUtilities.isTransitionNode(treeNode))
		{
			XPDLPackage xpdlPackage = GOD4JFactory.getGOD4J().getXPDLDocument();
			xpdlPackage.loadComponent();

			WorkflowTransition trans = (WorkflowTransition) treeNode.getWorkflowComponent();
			WorkflowProcess workflowProcess = trans.getWorkflowProcess();
			XPDLProcesses xpdl_processes = (XPDLProcesses) xpdlPackage.get("WorkflowProcesses");
			xpdl_processes.loadComponent();

			XPDLProcess xpdl_process = (XPDLProcess) xpdl_processes.findComponent(workflowProcess.getUUID());
			xpdl_process.loadComponent();

			XPDLTransitions xpdl_trans = (XPDLTransitions) xpdl_process.get("Transitions");
			xpdl_trans.loadComponent();

			XPDLTransition xpdl_tran = (XPDLTransition) xpdl_trans.findComponent(trans.getUUID());

			if (ActivityType.ACTIVITY_BEGIN.equals(trans.getFromWorkflowActivity().getActivityType())
				|| ActivityType.ACTIVITY_END.equals(trans.getToWorkflowActivity().getActivityType()))
			{
				xpdl_tran.setReadOnly(true);
			}

			JavaDialog dlg = new JavaDialog(GOD4JFactory.getGOD4J(),"");
			dlg.editXPDLComponent(xpdl_tran.getJavaPanel(), true, false);
			if (!dlg.isCanceled() && !xpdl_tran.isReadOnly())
			{
				GOD4JFactory.getGOD4J().setDirty(true);
				GOD4JFactory.getGOD4J().getExplorerPanel().getNodeExplorer().updateUI();
			}
		}
	}

	//----------------------------------------------------------------------------------------------
	public void addWorkflowParameter(WorkflowParameter parameter)
	{
		treeModel.addWorkflowParameter(parameter);
	}
	public void addWorkflowApplication(WorkflowApplication application)
	{
		treeModel.addWorkflowApplication(application);
	}

	public void addWorkflowActivity(WorkflowActivity activity)
	{
		treeModel.addWorkflowActivity(activity);
	}

	public void addWorkflowTransition(WorkflowTransition trans)
	{
		treeModel.addWorkflowTransition(trans);
	}

	public void addWorkflowProcess(WorkflowProcess process)
	{
		addWorkflowProcess(process, false);
	}
	public void addWorkflowProcess(WorkflowProcess process, boolean is_subprocess)
	{
		treeModel.addWorkflowProcess(process, is_subprocess);
	}

	public void removeWorkflowParameter(WorkflowParameter parameter)
	{
		treeModel.removeWorkflowParameter(parameter);
	}
	public void removeWorkflowApplication(WorkflowApplication application)
	{
		treeModel.removeWorkflowApplication(application);
	}

	public void removeWorkflowActivity(WorkflowActivity activity)
	{
		treeModel.removeWorkflowActivity(activity);
	}
	public void removeWorkflowTransition(WorkflowTransition trans)
	{
		treeModel.removeWorkflowTransition(trans);
	}

	public void removeWorkflowProcess(WorkflowProcess process)
	{
		treeModel.removeWorkflowProcess(process);
	}

	//----------------------------------------------------------------------------------------------
	public void showPopup(Point point)
	{
		DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) this.getLastSelectedPathComponent();
		if (treeNode != null)
		{
			JPopupMenu popup = createJPopupMenu((ExplorerNode)treeNode);
			if (popup != null)
			{
				popup.show(this, point.x, point.y);
			}
		}
	}

	protected JPopupMenu createJPopupMenu(ExplorerNode treeNode)
	{
		GOD4JFactory.getGOD4J().getActionMap().getAction("cut").setEnabled(false);				
		GOD4JFactory.getGOD4J().getActionMap().getAction("copy").setEnabled(false);
		GOD4JFactory.getGOD4J().getActionMap().getAction("delete").setEnabled(false);	
		GOD4JFactory.getGOD4J().getActionMap().getAction("editProperties").setEnabled(false);
		
		if (ExplorerUtilities.isNullNode(treeNode)
			|| ExplorerUtilities.isParametersNode(treeNode)
			|| ExplorerUtilities.isApplicationsNode(treeNode)
			|| ExplorerUtilities.isProcessesNode(treeNode)
			|| ExplorerUtilities.isActivitiesNode(treeNode)
			|| ExplorerUtilities.isTransitionsNode(treeNode))
		{
			return null;
		}

		JPopupMenu popup = new JPopupMenu();
		popup.add(createMenuItem("editProperties"));
		
		if (ExplorerUtilities.isProcessNode(treeNode))
		{
			popup.addSeparator();
			
			WorkflowProcess workflowProcess = (WorkflowProcess) treeNode.getWorkflowComponent();
			popup.add(BarFactory.createMenuItem(sm_god4j,"showGraph", new ShowGraph(workflowProcess)));
			popup.addSeparator();

			popup.add(createMenuItem("delete"));

		}
		else if (ExplorerUtilities.isActivityNode(treeNode))
		{
			popup.addSeparator();

			popup.add(createMenuItem("copy"));
			popup.add(createMenuItem("cut"));
			popup.add(createMenuItem("delete"));

		}
		return popup;
	}

	protected JMenuItem createMenuItem(String cmd)
	{
		ActionBase action = GOD4JFactory.getGOD4J().getActionMap().getAction(cmd);
		action.setEnabled(true);
		return BarFactory.createMenuItem(sm_god4j,cmd, action);
	}

	protected void cleanNodeExplorer()
	{
	}
}
