//----------------------------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.elements;

import java.util.ArrayList;

import org.huihoo.god4j.editor.XPDLAttribute;
import org.huihoo.god4j.editor.XPDLCollectionComponent;
import org.huihoo.god4j.editor.XPDLComplexChoice;
import org.huihoo.god4j.editor.XPDLComplexComponent;
import org.huihoo.god4j.editor.XPDLComponent;
import org.huihoo.god4j.editor.elements.set.XPDLActivities;
import org.huihoo.god4j.editor.elements.set.XPDLExtendedAttributes;
import org.huihoo.god4j.editor.elements.set.XPDLProcesses;
import org.huihoo.god4j.editor.panels.JavaComboxPanel;
import org.huihoo.god4j.editor.panels.JavaGroupPanel;
import org.huihoo.god4j.editor.panels.JavaPanel;
import org.huihoo.workflow.WorkflowComponent;
import org.huihoo.workflow.xpdl.WorkflowActivity;
import org.huihoo.workflow.xpdl.activity.ActivityType;
import org.huihoo.workflow.xpdl.activity.Implementation;
import org.huihoo.workflow.xpdl.activity.SubFlowImplementation;

/**
* Represents a WfMC DTD element that has the similar name.
*
* @see XPDL
*/
public class XPDLSubFlow extends XPDLComplexComponent
{
	private XPDLAttribute attrId = null;
	private XPDLExtendedAttributes refExtendedAttributes = null; // min=0
//----------------------------------------------------------------
	/** Choice of possible workflows. */
	private XPDLComplexChoice refProcessChoices;

	private transient XPDLProcesses definedProcesses = null;
	/** Enables canceling of changes to the extended attributes collection. */
	private XPDLExtendedAttributes clonedEAs;

	/**
	* Creates a new instance of the class.
	*
	* @param act The activity that holds this element.
	*/
	public XPDLSubFlow(XPDLComplexComponent parent)
	{
		super(parent);
	}

	public XPDLProcess  getChoosenProcess()
	{
		return (XPDLProcess) refProcessChoices.getChoosen();
	}
	
	/**
	* Uses a trick to set the cloned instance of actual parameters to
	* be edited, so that canceling of changes to the actual parameter
	* collection can be handled - the real instance of actual parameters
	* is set to the cloned instance within the isValidData method.
	*/
	public JavaPanel getJavaPanel()
	{
		clonedEAs = (XPDLExtendedAttributes) refExtendedAttributes.clone();
		JavaPanel p = new JavaGroupPanel(this, new XPDLComponent[] { refProcessChoices,clonedEAs }, getLabel());
		return p;
	}

	/**
	* Used to create exact copy of instance of this class.
	* The newly created instance will have all the properties
	* same as the copied one.
	*
	* @return The newly created instance of this class.
	*/
	public Object clone()
	{
		XPDLSubFlow s = (XPDLSubFlow) super.clone();
		s.attrId = (XPDLAttribute) this.attrId.clone();	
		s.refExtendedAttributes = (XPDLExtendedAttributes) this.refExtendedAttributes.clone();
		
		s.definedProcesses = this.definedProcesses;
	
		XPDLImplementation xpdlImpl = (XPDLImplementation) s.getParentComponent();
		XPDLActivity xpAct = (XPDLActivity) xpdlImpl.getParentComponent();
		XPDLActivities xpActs = (XPDLActivities) xpAct.getOwnerCollection();

		final XPDLProcess xpProcess = (XPDLProcess) xpActs.getParentComponent();
		XPDLProcesses xpProcesses = (XPDLProcesses) xpProcess.getOwnerCollection();
		XPDLPackage xpPackage = (XPDLPackage) xpProcesses.getParentComponent();
		final XPDLProcess xpMainProcess = xpPackage.getMainProcess();
		
		s.refProcessChoices = new XPDLComplexChoice(this, "WorkflowProcess", null, 0)
		{
			public JavaPanel getJavaPanel()
			{
				ArrayList ws = new ArrayList();
				ws.addAll(definedProcesses.getComboxComponents());
				ws.remove(xpProcess);
				ws.remove(xpMainProcess);
				choices = ws.toArray();

				if (this.getChoosen() == null && choices != null && choices.length > 0)
				{
					this.setValue(choices[0]);
				}
				return new JavaComboxPanel(this, choices);
			}

			public void setValue(Object v)
			{
				super.setValue(v);
				try
				{
					attrId.setValue(((XPDLCollectionComponent) this.getChoosen()).getUUID());
				}
				catch (Exception ex)
				{
				}
			}

		};
		s.refProcessChoices.initComponent();
		s.refProcessChoices.setValue(refProcessChoices.getChoosen());
		s.refProcessChoices.setRequired(true);
		
		s.clonedEAs = null;
		
		s.structComponent();

		return s;
	}

	/**
	 * Checks if actual and formal params are matched by type and number.
	 * This method is called only if user doesn't press Cancel button
	 * within the dialog for editing Tool properties, so the changes to
	 * the real collection of actual parameters are applied here.
	 * @param groupPanel The panel for editing parameters.
	 * @return <tt>true</tt> if actual and formal parameter types and number
	 *         are matching, <tt>false</tt> otherwise.
	 */
	public boolean isInputValid(JavaPanel groupPanel)
	{
		boolean isValidEnter = super.isInputValid(groupPanel);
		XPDLProcess xpProcess = (XPDLProcess) refProcessChoices.getChoosen();
		if (xpProcess == null)
		{
  		String message = sm.getString("ErrorSubFlowActivitySuboprocessMustProvided");
  		String dialogTitle = sm.getString("DialogSubFlowActivitySuboprocessMustProvided");
  		String elementTitle = getLabel() + ": ";
			
			JavaPanel.errorMessage(groupPanel.getDialog(), dialogTitle, elementTitle, message);
			
			return false;
		}
		
		if(isValidEnter)
		{
			if (clonedEAs != null)
			{
				complexChildren.remove(refExtendedAttributes);
				refExtendedAttributes = clonedEAs;
				complexChildren.add(2, refExtendedAttributes);
			}
		}
		return isValidEnter;
	}

	//==================================================================
	public void initComponent()
	{
		//	-----------------------------------------------
		super.initComponent();
		//	-----------------------------------------------	
		attrId = new XPDLAttribute(this, "Id");
		attrId.initComponent();
		attrId.setRequired(true);
		attrId.setReadOnly(true);

		refExtendedAttributes = new XPDLExtendedAttributes(this); // min=0
		refExtendedAttributes.initComponent();
		
		XPDLImplementation xpdlImpl = (XPDLImplementation) getParentComponent();
		XPDLActivity xpAct = (XPDLActivity) xpdlImpl.getParentComponent();
		XPDLActivities xpActs = (XPDLActivities) xpAct.getOwnerCollection();

		XPDLProcess xpProcess = (XPDLProcess) xpActs.getParentComponent();
		XPDLProcesses xpProcesses = (XPDLProcesses) xpProcess.getOwnerCollection();
		XPDLPackage xpPackage = (XPDLPackage) xpProcesses.getParentComponent();

		XPDLImplementation myImpl = (XPDLImplementation) getParentComponent();
		XPDLActivity myAct = (XPDLActivity) myImpl.getParentComponent();
		final XPDLProcess myProcess = (XPDLProcess) myAct.getParentComponent();
		final XPDLPackage myPackage = (XPDLPackage) myProcess.getParentComponent();
		final XPDLProcess xpMainProcess = xpPackage.getMainProcess();
		definedProcesses = (XPDLProcesses) myPackage.get("WorkflowProcesses");

		refProcessChoices = new XPDLComplexChoice(this, "WorkflowProcess", null, 0)
		{
			public JavaPanel getJavaPanel()
			{
				ArrayList ws = new ArrayList();
				ws.addAll(definedProcesses.getComboxComponents());
				ws.remove(myProcess);
				ws.remove(xpMainProcess);
				choices = ws.toArray();

				if (this.getChoosen() == null && choices != null && choices.length > 0)
				{
					this.setValue(choices[0]);
				}
				return new JavaComboxPanel(this, choices);
			}

			public void setValue(Object v)
			{
				super.setValue(v);
				try
				{
					attrId.setValue(((XPDLCollectionComponent) this.getChoosen()).getUUID());
				}
				catch (Exception ex)
				{
				}
			}

		};
		refProcessChoices.initComponent();
		refProcessChoices.setRequired(true);
	}

	public void structComponent()
	{
		//	-----------------------------------------------
		super.structComponent();
		//	-----------------------------------------------
		attrId.structComponent();
		refProcessChoices.structComponent();
		refExtendedAttributes.structComponent();
		
		complexChildren.add(attrId);
		complexChildren.add(refProcessChoices);
		complexChildren.add(refExtendedAttributes);
		

		attributes.add(attrId);
	}


	public void loadComponent()
	{
		//	-----------------------------------------------
		super.loadComponent();
		//	-----------------------------------------------
		attrId.loadComponent();
		
		refProcessChoices.loadComponent();
		refExtendedAttributes.loadComponent();
		
		XPDLImplementation xpImpl = (XPDLImplementation)getParentComponent();
		XPDLActivity xpAct = (XPDLActivity) xpImpl.getParentComponent();
		WorkflowComponent workflow_component = xpAct.getWorkflowComponent();
		if (workflow_component == null || !(workflow_component instanceof WorkflowActivity))
		{
			return;
		}
		
		Implementation impl = ((WorkflowActivity)workflow_component).getImplementation();
		if (impl == null || !(impl instanceof SubFlowImplementation))
		{
			return;
		}
		SubFlowImplementation subflowImpl = (SubFlowImplementation) impl;

		if (subflowImpl != null)
		{
			attrId.setValue(subflowImpl.getProcessID());
			XPDLProcess xpProcess = (XPDLProcess) definedProcesses.getXPDLProcess(subflowImpl.getProcessID());
			refProcessChoices.setValue(xpProcess);
		}
	}


	public void saveComponent()
	{
    if(isReadOnly())
    {
      return;
    }
    
    
		//	-----------------------------------------------
		super.saveComponent();
		//	-----------------------------------------------
		attrId.saveComponent();
		refProcessChoices.saveComponent();
		refExtendedAttributes.saveComponent();
		
		XPDLProcess xpProcess = (XPDLProcess) refProcessChoices.getChoosen();
		if (xpProcess != null)
		{
			attrId.setValue(xpProcess.getUUID());
		}
		
		XPDLImplementation xpImpl = (XPDLImplementation)getParentComponent();
		XPDLActivity xpAct = (XPDLActivity) xpImpl.getParentComponent();
		WorkflowComponent workflow_component = xpAct.getWorkflowComponent();
		if (workflow_component == null || !(workflow_component instanceof WorkflowActivity))
		{
			return;
		}
		
		WorkflowActivity wfAct = (WorkflowActivity)workflow_component;
		if(! ActivityType.ACTIVITY_SUBFLOW.equals(wfAct.getActivityType()))
		{
			return;
		}
		wfAct.setImplementation(null);
		
		SubFlowImplementation subflowImpl = new SubFlowImplementation();
		saveComponent(subflowImpl);
		wfAct.setImplementation(subflowImpl);
	}
	public void saveComponent(WorkflowComponent workflow_component)
	{
		//	-----------------------------------------------
		super.saveComponent(workflow_component);
		//	-----------------------------------------------	
		attrId.saveComponent(workflow_component);
		refProcessChoices.saveComponent(workflow_component);
		refExtendedAttributes.saveComponent(workflow_component);
		
		XPDLProcess xpProcess = (XPDLProcess) refProcessChoices.getChoosen();
		if (xpProcess != null)
		{
			attrId.setValue(xpProcess.getUUID());
		}

		if (workflow_component != null && (workflow_component instanceof SubFlowImplementation))
		{
			SubFlowImplementation simple_component = (SubFlowImplementation) workflow_component;
			simple_component.setProcessID(attrId.toString());
		}

	}
	//==================================================================
}
