//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.layout.elements;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.ElementLayoutManager;
import org.eclipse.epf.library.layout.IElementLayout;
import org.eclipse.epf.library.layout.util.XmlElement;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.Process;

import com.ibm.icu.util.StringTokenizer;


/**
 * abstrct class for process element layout that is process specific
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public abstract class AbstractProcessElementLayout extends
		AbstractElementLayout {

	protected Process owningProcess = null;

	protected String elementProcessPath = null;
	protected String relProcessPath = null;
	protected String[] paths = null;
	
	// protected String urlParameter
	public void init(ElementLayoutManager layoutManager, MethodElement element,
			Process owningProc, String path) {

		init(layoutManager, element);

		this.owningProcess = owningProc;
		this.elementProcessPath = path;

		if (this.owningProcess == null) {
			this.owningProcess = TngUtil
					.getOwningProcess((BreakdownElement) super.element);
		}

		if (element instanceof Process) {
			owningProcess = (Process) element;
			elementProcessPath = AbstractProcessElementLayout.makePath(null,
					element);
			relProcessPath = elementProcessPath;
		}
		
		if ( elementProcessPath == null && this.element instanceof BreakdownElement)
		{
			elementProcessPath = AbstractProcessElementLayout.getPath((BreakdownElement)this.element);
		}
		
		// get the path array
		paths = getPathArray(elementProcessPath);
		
	}


	/**
	 * the process path of this item relative to the calling item
	 * @param path
	 */
	public void setRelativeProcessPath(String path)
	{
		this.relProcessPath = path;
	}
	
	public String getRelativeProcessPath()
	{
		return this.relProcessPath;
	}
	
//	public String getUrl() {
//		String url = super.getUrl();
//
//		return url + getQueryString();
//	}

	public String getQueryString() {
//		if (owningProcess == element) {
//			return "";
//		}
		// return "?" + ResourceHelper.URL_PARAMETER_PROCESS + "=" +
		// owningProcess.getGuid() + "&" + ResourceHelper.URL_PARAMETER_PATH +
		// "=" + elementProcessPath;

		return ElementLayoutManager.getQueryString(owningProcess.getGuid(),
				elementProcessPath);
	}

	protected XmlElement getXmlElement() {
		XmlElement elementXml = super.getXmlElement();
		elementXml.setAttribute("queryString", getQueryString()) //$NON-NLS-1$
			//.setAttribute("owningProcessGuid", owningProcess.getGuid()) // //$NON-NLS-1$
			//.setAttribute("elementProcessPath", elementProcessPath) //$NON-NLS-1$
			.setAttribute("relProcessPath", relProcessPath); //$NON-NLS-1$

		return elementXml;
	}
	
	protected Process getOwningProcess() {
		return owningProcess;
	}

	protected IElementLayout getLayout(ProcessElementItem item) {
		IElementLayout layout = layoutManager.createLayout(item.element, owningProcess, item.path);
		
		if ( layout instanceof AbstractProcessElementLayout )
		{		
			// set the relative path to this layout since this is the caller
			String relPath = AbstractProcessElementLayout.getRelativePath(item.path, this.elementProcessPath);
			((AbstractProcessElementLayout)layout).setRelativeProcessPath(relPath);
		}
		return layout;
	}

	// static utility methods for process layout
	public static String makePath(String parentPath, MethodElement element) {
		if (parentPath == null || parentPath.length() == 0) {
			return element.getGuid();
		}

		return parentPath + "," + element.getGuid();
	}

	public static String getPath(BreakdownElement element) {
		
		String path = element.getGuid();
		BreakdownElement act = element;
		
		// Check superactivity is process and should owning process (this is useful in deepcopy
		while ( !((act instanceof Process) && act.equals(TngUtil.getOwningProcess(element))) )
		{
			Activity superActs = act.getSuperActivities();
			if ( superActs != null )
			{
				act = superActs;
				path = act.getGuid() + "," + path;
			}
			else
			{
				break;
			}
		}
		
		return path;		
	}
	
	/**
	 * get the path for a given breakdown element item provider
	 * @param wrapper BreakdownElementWrapperItemProvider
	 * @return String the path
	 */
	public static String getPath(BreakdownElementWrapperItemProvider wrapper)
	{
		Object e = LibraryUtil.unwrap(wrapper);
		if ( !(e instanceof MethodElement) ) {
			return null;
		}
		Object topItem = wrapper.getTopItem();
		StringBuffer path = new StringBuffer();
		path.append(((MethodElement)e).getGuid());
		
		Object parent = wrapper;
		while (parent != null && parent != topItem) {
			if ( parent instanceof BreakdownElement ) {
				parent = ((BreakdownElement)parent).getSuperActivities();
				e = parent;
			} else if ( parent instanceof BreakdownElementWrapperItemProvider ){
				parent = ((BreakdownElementWrapperItemProvider)parent).getParent(parent);
				e = LibraryUtil.unwrap(parent);
			} else {
				break;
			}
			
			if ( e instanceof MethodElement) {
				path.insert(0, ((MethodElement)e).getGuid() + ",");
			}
		}
		
		return path.toString();
	}
	
	
	public static String getRelativePath(String path, String parentPath) {
		
		if ( path == null )
		{
			return path;
		}
		
		if ( path.startsWith(parentPath) )
		{
			return path.substring(parentPath.length());
		}
		
		return path;
	}

	public static String[] getPathArray(String path)
	{
		if ( path == null )
		{
			return new String[]{};			
		}
		
		List items = new ArrayList();
		StringTokenizer st = new StringTokenizer(path, ",");
		while ( st.hasMoreTokens() )
		{
			String s = st.nextToken().trim();
			if ( s.length() > 0 )
			{
				items.add(s);
			}
		}
		
		String[] arr = new String[items.size()];
		items.toArray(arr);
		
		return arr;
	}
	
	/**
	 * get the owning process from path, the first part of the path is the guid of the process
	 * @param path
	 * @return String
	 */
	public static String getOwningProcessGuidFromPath(String path)
	{
		if ( path == null )
		{
			return null;
		}
		
		int index = path.indexOf(",");
		String guid;
		if ( index < 0 )
		{
			guid = path;
		}
		else
		{
			guid = path.substring(0, index);
		}
		
		return guid;
	}

	public static String getParentPath(String path) {
		if ( path == null ) {
			return null;
		}
		
		int index = path.lastIndexOf(",");
		if ( index > 0 ) {
			return path.substring(0, index);
		}
		
		return null;
	}
}
