//------------------------------------------------------------------------------
// 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.common.serviceability;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.epf.common.CommonPlugin;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;

/**
 * Provides utilities to query a method library schema and the version of the
 * tool that created it.
 * 
 * @author Jeff Hardy
 * @since 1.0
 */
public class VersionUtil {

	public static class VersionCheckInfo {
		public VersionCheckInfo(String id, String toolVersion,
				String currentMinToolVersion, int result) {
			this.toolID = id;
			this.toolVersion = toolVersion;
			this.currentMinToolVersion = currentMinToolVersion;
			this.result = result;
		}

		public String toolID;

		public String toolVersion;

		public String currentMinToolVersion;

		/**
		 * < 0: fileToolVersion is older than currentMinToolVersion <br/> == 0:
		 * match <br/> > 0 : fileToolVersion is newer than currentMinToolVersion
		 * <br/>
		 */
		public int result;
	}

	/**
	 * The extension point namespace.
	 */
	public static final String EXTENSION_POINT_NAMESPACE = CommonPlugin.class
			.getPackage().getName();

	/**
	 * The extension point name.
	 */
	public static final String EXTENSION_POINT_NAME = "version"; //$NON-NLS-1$

	public static final String EXTENSION_VERSIONS_INFO = "versions"; //$NON-NLS-1$

	public static final String EXTENSION_LIB_EXTENSION_CHECK = "libraryExtensionVersionCheck"; //$NON-NLS-1$

	private static final String DISABLE_VERSION_CHECKING_PREF = "disable_version_checking"; //$NON-NLS-1$

	public static Map versions = new LinkedHashMap();

	public static Map libExtCheckers = new LinkedHashMap();

	protected static boolean versionCheckingDisabled = false;

	/**
	 * List of toolIDs to check, in order
	 */
	private static List toolIDsCheckList = new ArrayList();

	static {
		toolIDsCheckList.add(EPFVersions.TOOL_ID);

		// read properties file
		try {
			String valueStr = CommonPlugin.getDefault().getPreferenceStore()
					.getString(DISABLE_VERSION_CHECKING_PREF);
			versionCheckingDisabled = Boolean.valueOf(valueStr).booleanValue();
		} catch (MissingResourceException e) {
			versionCheckingDisabled = false;
		}

		// Process the "org.eclipse.epf.common.version" extension point
		// contributors.
		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
		IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(
				EXTENSION_POINT_NAMESPACE, EXTENSION_POINT_NAME);
		if (extensionPoint != null) {
			IExtension[] extensions = extensionPoint.getExtensions();
			for (int i = 0; i < extensions.length; i++) {
				IExtension extension = extensions[i];
				initExtension(extension);
			}
		}

	}

	protected static void initExtension(IExtension extension) {
		String extensionID = extension.getSimpleIdentifier();
		String pluginId = extension.getNamespaceIdentifier();
		Bundle bundle = Platform.getBundle(pluginId);
		IConfigurationElement[] configElements = extension
				.getConfigurationElements();
		for (int j = 0; j < configElements.length; j++) {
			IConfigurationElement configElement = configElements[j];
			try {
				if (EXTENSION_VERSIONS_INFO.equals(configElement.getName())) {
					String className = configElement.getAttribute("class"); //$NON-NLS-1$
					if (className != null) {
						versions.put(extensionID, (EPFVersions) bundle
								.loadClass(className).newInstance());
						break;
					}
				}
				if (EXTENSION_LIB_EXTENSION_CHECK.equals(configElement
						.getName())) {
					String className = configElement.getAttribute("class"); //$NON-NLS-1$
					if (className != null) {
						libExtCheckers.put(extensionID,
								(ILibraryExtensionVersionCheck) bundle
										.loadClass(className).newInstance());
						break;
					}
				}
			} catch (Exception e) {
				CommonPlugin.getDefault().getLogger().logError(e);
			}
		}
	}

	/**
	 * 
	 * @return the map of Tool IDs-to-Versions class
	 */
	public static Map getVersionsMap() {
		return Collections.unmodifiableMap(versions);
	}

	/**
	 * 
	 * @return a Set of all known Tool IDs
	 */
	public static Set getAllToolIDs() {
		return Collections.unmodifiableSet(versions.keySet());
	}

	/**
	 * 
	 * @param toolID
	 * @return The Versions class for the given Tool ID
	 */
	public static EPFVersions getVersions(String toolID) {
		return (EPFVersions) versions.get(toolID);
	}

	/**
	 * 
	 * @return true iff version checking is disabled
	 */
	public static boolean isVersionCheckingDisabled() {
		return versionCheckingDisabled;
	}

	public static final Pattern p_XMIVersionPattern = Pattern.compile(
			"(\\w+?):version=\"(.+?)\"", Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_XMLVersionAttributePattern = Pattern.compile(
			"tool=\"(.*?)\"", Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_XMI_ELEMENT_START_TAG = Pattern
			.compile("<?xml version=\".+?\" encoding=\".+?\"?>"); //$NON-NLS-1$

	public static final String XML_ELEMENT_END_TAG = ">"; //$NON-NLS-1$

	public static final String XMI_ATTRIBUTE_TAG = "xmi"; //$NON-NLS-1$

	public static final String XML_ELEMENT_START_TAG = "<uma:MethodLibrary"; //$NON-NLS-1$

	public static final String XML_VERSIONS_SEPARATOR = ";"; //$NON-NLS-1$

	public static final String XML_TOOL_VERSION_SEPARATOR = "="; //$NON-NLS-1$

	/**
	 * Given an XML file, will read the tool="foo=a.b.c.d;bar=w.x.y.z"
	 * attributes and return a map of the id-to-versions.
	 * 
	 * @param xmlFile
	 *            file to process
	 * @return null if no versions found; a map of the id-to-versions otherwise
	 */
	protected static Map readVersionsFromXMLFile(File xmlFile) {
		Map versions = new LinkedHashMap();
		StringBuffer buf = null;
		try {
			buf = FileUtil.readFile(xmlFile, FileUtil.ENCODING_UTF_8);
		} catch (Exception ex) {
			CommonPlugin.getDefault().getLogger().logError(ex);
		}
		if (buf != null) {
			int xmiElementStartIdx = buf.indexOf(XML_ELEMENT_START_TAG);
			if (xmiElementStartIdx != -1) {
				int xmiElementEndIdx = buf.indexOf(XML_ELEMENT_END_TAG,
						xmiElementStartIdx + XML_ELEMENT_START_TAG.length());
				if (xmiElementEndIdx != -1) {
					String rootElement = buf.substring(xmiElementStartIdx,
							xmiElementEndIdx);
					Matcher mAttribute = p_XMLVersionAttributePattern
							.matcher(rootElement);
					if (mAttribute.find()) {
						String toolsAttribute = mAttribute.group(1);
						if (toolsAttribute != null
								&& toolsAttribute.length() > 0) {
							String[] versionsArray = StrUtil.split(
									toolsAttribute, XML_VERSIONS_SEPARATOR);
							for (int i = 0; i < versionsArray.length; i++) {
								if (versionsArray[i] != null
										&& versionsArray[i].length() > 0) {
									String[] versionInfoArray = StrUtil.split(
											versionsArray[i],
											XML_TOOL_VERSION_SEPARATOR);
									if (versionInfoArray.length != 2)
										continue;
									String toolID = versionInfoArray[0];
									String toolVersion = versionInfoArray[1];
									if (toolID != null
											&& toolID.trim().length() > 0
											&& toolVersion != null
											&& toolVersion.trim().length() > 0)
										versions.put(toolID, toolVersion);
								}
							}
						}
					}
				}
			}
		}
		if (versions.size() == 0) {
			return null;
		} else {
			return versions;
		}
	}

	/**
	 * Given an XMI file, will read the foo:version="x.x.x" attributes and
	 * return a map of the id-to-versions.
	 * 
	 * @param xmlFile
	 *            file to process
	 * @return null if no versions found; a map of the id-to-versions otherwise
	 */
	protected static Map readVersionsFromXMIFile(File xmiFile) {
		Map versions = new LinkedHashMap();
		StringBuffer buf = null;
		try {
			buf = FileUtil.readFile(xmiFile, FileUtil.ENCODING_UTF_8);
		} catch (Exception ex) {
			CommonPlugin.getDefault().getLogger().logError(ex);
		}
		if (buf != null) {
			Matcher docStartMatcher = p_XMI_ELEMENT_START_TAG.matcher(buf);
			if (docStartMatcher.find()) {
				int docHeaderEndIdx = docStartMatcher.end();
				int xmiElementEndIdx = buf.indexOf(XML_ELEMENT_END_TAG,
						docHeaderEndIdx);
				if (xmiElementEndIdx != -1) {
					String rootElement = buf.substring(docHeaderEndIdx,
							xmiElementEndIdx + 1);
					Matcher m = p_XMIVersionPattern.matcher(rootElement);
					while (m.find()) {
						String toolID = m.group(1);
						if (toolID.equals(XMI_ATTRIBUTE_TAG))
							continue;
						String toolVersion = m.group(2);
						if (toolID != null && toolID.trim().length() > 0
								&& toolVersion != null
								&& toolVersion.trim().length() > 0)
							versions.put(toolID, toolVersion);
					}
				}
			}
		}
		if (versions.size() == 0) {
			return null;
		} else {
			return versions;
		}
	}

	/**
	 * Given a file, will read version information and return a map of the
	 * id-to-versions.
	 * 
	 * @param file
	 *            file to process
	 * @return null if no versions found; a map of the id-to-versions otherwise
	 */
	public static Map readVersionsFromFile(File file) {
		if (file.getName().toUpperCase().endsWith("XMI")) { //$NON-NLS-1$
			return readVersionsFromXMIFile(file);
		} else if (file.getName().toUpperCase().endsWith("XML")) { //$NON-NLS-1$
			return readVersionsFromXMLFile(file);
		} else {
			Map versions = readVersionsFromXMIFile(file);
			if (versions != null)
				return versions;
			versions = readVersionsFromXMLFile(file);
			if (versions != null)
				return versions;
		}
		return null;
	}

	/**
	 * Given a file, will compare with current XML Schema version.
	 * 
	 * @param file
	 * @return null if file tool version can not be found; a VersionCheckInfo
	 *         object otherwise
	 */
	public static VersionCheckInfo checkXMLVersion(File file) {
		Map versionMap = VersionUtil.readVersionsFromFile(file);
		if (versionMap == null) {
			return null;
		} else {
			VersionCheckInfo vci = null;
			for (Iterator iter = toolIDsCheckList.iterator(); iter.hasNext();) {
				String toolID = (String) iter.next();
				if (versionMap.get(toolID) != null) {
					String toolVersion = (String) versionMap.get(toolID);
					vci = _checkXMLVersion(toolID, toolVersion);
					if (vci != null)
						return vci;
				}
			}
		}
		return null;
	}

	private static VersionCheckInfo _checkXMLVersion(String toolID,
			String toolVersion) {
		// get the class that stores all the version info for this tool ID
		EPFVersions versions = getVersions(toolID);
		if (versions != null) {
			EPFVersion minCurrVersion = versions
					.getMinToolVersionForCurrentXMLSchemaVersion();
			int result = minCurrVersion.compareToolVersionTo(new Version(
					toolVersion));
			String currentMinToolVersion = minCurrVersion.getToolVersion()
					.toString();
			return new VersionCheckInfo(toolID, toolVersion,
					currentMinToolVersion, -result);
		}
		return null;
	}

	/**
	 * Given a file, compares with current library schema version
	 * 
	 * @param file
	 * @return null if file tool version can not be found; a VersionCheckInfo
	 *         object otherwise
	 */
	public static VersionCheckInfo checkLibraryVersion(File file) {
		if (file.getName().equals("library.xmi")) { //$NON-NLS-1$
			// check library extensions first
			for (Iterator iter = toolIDsCheckList.iterator(); iter.hasNext();) {
				String toolID = (String) iter.next();
				if (libExtCheckers.get(toolID) != null) {
					VersionCheckInfo vci = null;
					ILibraryExtensionVersionCheck extCheck = (ILibraryExtensionVersionCheck) libExtCheckers
							.get(toolID);
					vci = extCheck.checkLibraryVersion(file.getParentFile());
					if (vci != null)
						return vci;
				}
			}
		}
		Map versionMap = VersionUtil.readVersionsFromFile(file);
		if (versionMap == null) {
			return null;
		} else {
			VersionCheckInfo vci = null;
			for (Iterator iter = toolIDsCheckList.iterator(); iter.hasNext();) {
				String toolID = (String) iter.next();
				if (versionMap.get(toolID) != null) {
					String toolVersion = (String) versionMap.get(toolID);
					vci = _checkLibVersion(toolID, toolVersion);
					if (vci != null)
						return vci;
				}
			}
		}
		return null;
	}

	private static VersionCheckInfo _checkLibVersion(String toolID,
			String toolVersion) {
		// get the class that stores all the version info for this tool ID
		EPFVersions versions = getVersions(toolID);
		if (versions != null) {
			EPFVersion minCurrVersion = versions
					.getMinToolVersionForCurrentLibraryVersion();
			int result = minCurrVersion.compareToolVersionTo(new Version(
					toolVersion));
			String currentMinToolVersion = minCurrVersion.getToolVersion()
					.toString();
			return new VersionCheckInfo(toolID, toolVersion,
					currentMinToolVersion, -result);
		}
		return null;
	}

	/**
	 * 
	 * @return the first toolID that is checked. In most cases, the ID of the
	 *         currently running application
	 */
	public static String getPrimaryToolID() {
		return (String) toolIDsCheckList.get(0);
	}

	/**
	 * Adds a tool ID to the order of tools to check.
	 * 
	 * @param toolID
	 *            toolID to add
	 * @param toolIDfollowing
	 *            if null, adds toolID to front of list. otherwise, adds toolID
	 *            before the specified ID
	 * @return false iff toolIDfollowing is not null and could not be found in
	 *         list; true otherwise
	 */
	public static boolean addToolID(String toolID, String toolIDfollowing) {
		if (toolIDfollowing != null) {
			int idx = toolIDsCheckList.indexOf(toolIDfollowing);
			if (idx != -1) {
				toolIDsCheckList.add(idx, toolID);
				return true;
			} else {
				return false;
			}
		}
		toolIDsCheckList.add(0, toolID);
		return true;
	}

}
