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

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.ProcessFamily;

/**
 * Helper utilities for managing a method library.
 * 
 * @author Kelvin Low
 * @since 1.0
 */
public class LibraryServiceUtil {

	/**
	 * Gets the method library path.
	 * 
	 * @param library
	 *            a method library
	 * @return an absolute path to the method library
	 */
	public static String getMethodLibraryPath(MethodLibrary library) {
		Resource resource = library.eResource();
		if (resource != null) {
			URI resourceURI = resource.getURI();
			if (resourceURI != null) {
				String path = resourceURI.toFileString();
				return new File(path).getParentFile().getAbsolutePath();
			}
		}
		return null;
	}

	/**
	 * Gets the method library path.
	 * 
	 * @param library
	 *            a method library
	 * @return an absolute path to the method library
	 */
	public static String getCurrentMethodLibraryPath() {
		return getMethodLibraryPath(LibraryService.getInstance()
				.getCurrentMethodLibrary());
	}

	/**
	 * Gets the parent method library of a method element.
	 * 
	 * @param element
	 *            a method element
	 * @return a method library
	 */
	public static MethodLibrary getMethodLibrary(MethodElement element) {
		for (EObject obj = element; obj != null; obj = obj.eContainer()) {
			if (obj instanceof MethodLibrary) {
				return (MethodLibrary) obj;
			}
		}
		return null;
	}

	/**
	 * Gets the method configuration in a method library.
	 * 
	 * @param library
	 *            a method library
	 * @param name
	 *            the method configuration name
	 * @return a method configuration
	 */
	public static MethodConfiguration getMethodConfiguration(
			MethodLibrary library, String name) {
		if (library != null) {
			MethodConfiguration config;
			List configs = library.getPredefinedConfigurations();
			for (Iterator it = configs.iterator(); it.hasNext();) {
				config = (MethodConfiguration) it.next();
				if (!(config instanceof ProcessFamily)
						&& config.getName().equals(name)) {
					return config;
				}
			}
		}
		return null;
	}

	/**
	 * Gets the method configurations in a method library.
	 * 
	 * @param library
	 *            a method library
	 * @return an array of method configurations.
	 */
	public static MethodConfiguration[] getMethodConfigurations(
			MethodLibrary library) {
		List configs;
		if (library != null) {
			MethodConfiguration config;
			configs = new ArrayList(library.getPredefinedConfigurations());
			for (Iterator i = configs.iterator(); i.hasNext();) {
				config = (MethodConfiguration) i.next();
				if (config == null || config instanceof ProcessFamily) {
					i.remove();
				}
			}
		}
		else {
			configs = Collections.EMPTY_LIST;
		}
		MethodConfiguration[] result = new MethodConfiguration[configs
				.size()];
		configs.toArray(result);
		return result;
	}

	/**
	 * Gets the method configuration names in a method library.
	 * 
	 * @param library
	 *            a method library
	 * @param name
	 *            the method configuration name
	 * @return an array of method configuration names
	 */
	public static String[] getMethodConfigurationNames(MethodLibrary library) {
		List configNames = new ArrayList();
		if (library != null) {
			MethodConfiguration config;
			List configs = library.getPredefinedConfigurations();
			for (Iterator i = configs.iterator(); i.hasNext();) {
				config = (MethodConfiguration) i.next();
				if (!(config instanceof ProcessFamily)) {
					configNames.add(config.getName());
				}
			}
		}
		String[] result = new String[configNames.size()];
		configNames.toArray(result);
		return result;
	}

	/**
	 * Gets the process family names in a method library.
	 * 
	 * @param library
	 *            a method library
	 * @param name
	 *            the method configuration name
	 * @return an array of process family names
	 */
	public static String[] getProcessFamilyNames(MethodLibrary library) {
		List processFamilyNames = new ArrayList();
		if (library != null) {
			MethodConfiguration config;
			List configs = library.getPredefinedConfigurations();
			for (Iterator i = configs.iterator(); i.hasNext();) {
				config = (MethodConfiguration) i.next();
				if (config instanceof ProcessFamily) {
					processFamilyNames.add(config.getName());
				}
			}
		}

		String[] result = new String[processFamilyNames.size()];
		processFamilyNames.toArray(result);

		return result;
	}

	/**
	 * Sets the GUID for a method element.
	 * 
	 * @param element
	 *            a method element
	 */
	public void setGUID(MethodElement element) {
		String guid = element.getGuid();
		if (guid == null || guid.length() == 0) {
			guid = EcoreUtil.generateUUID();
			boolean oldNotify = element.eDeliver();
			try {
				element.eSetDeliver(false);
				element.setGuid(guid);
			} finally {
				element.eSetDeliver(oldNotify);
			}
		}

		List children = element.eContents();
		if (children != null && children.size() > 0) {
			for (Iterator it = children.iterator(); it.hasNext();) {
				Object child = it.next();
				if (child instanceof MethodElement) {
					setGUID((MethodElement) child);
				}
			}
		}
	}

	/**
	 * Gets the debug string for a Method Element.
	 * 
	 * @element a method element
	 * @return a string containing the method element class name, name and GUID
	 */
	public static String getDebugStr(MethodElement element) {
		if (element == null) {
			return "null";
		}
		return element.getClass().getName() + "[name: " + element.getName()
				+ ", guid=" + element.getGuid() + "]";
	}

	/**
	 * Gets the HTTP query string for a process.
	 */
	public static String getQueryString(String process, String path) {
		return "?" + ResourceHelper.URL_PARAMETER_PROCESS + "=" + process + "&"
				+ ResourceHelper.URL_PARAMETER_PATH + "=" + path;
	}

}
