/*******************************************************************************
 * Copyright (c) 2004, 2012 Tasktop Technologies 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:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.commons.core;

import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

/**
 * @since 3.0
 * @author Steffen Pingel
 * @author Benjamin Muskalla
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public class CoreUtil {

	/**
	 * @since 3.0
	 */
	public static final boolean TEST_MODE;

	static {
		String application = System.getProperty("eclipse.application", ""); //$NON-NLS-1$ //$NON-NLS-2$
		if (application.length() > 0) {
			TEST_MODE = application.endsWith("testapplication") || application.endsWith("uitest"); //$NON-NLS-1$ //$NON-NLS-2$
		} else {
			// eclipse 3.3 does not the eclipse.application property
			String commands = System.getProperty("eclipse.commands", ""); //$NON-NLS-1$ //$NON-NLS-2$
			TEST_MODE = commands.contains("testapplication\n"); //$NON-NLS-1$
		}
	}

	private static final String FRAMEWORK_VERSION = "3.14.2"; //$NON-NLS-1$

	private static final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
	static {
		saxParserFactory.setNamespaceAware(true);
	}

	/**
	 * Returns a string representation of <code>object</code>. If object is a map or array the returned string will
	 * contains a comma separated list of contained elements.
	 * 
	 * @since 3.4
	 */
	public static String toString(Object object) {
		StringBuilder sb = new StringBuilder();
		toString(sb, object);
		return sb.toString();
	}

	private static void toString(StringBuilder sb, Object object) {
		if (object instanceof Object[]) {
			sb.append("["); //$NON-NLS-1$
			Object[] entries = (Object[]) object;
			boolean prependSeparator = false;
			for (Object entry : entries) {
				if (prependSeparator) {
					sb.append(", "); //$NON-NLS-1$
				}
				toString(sb, entry);
				prependSeparator = true;
			}
			sb.append("]"); //$NON-NLS-1$
		} else if (object instanceof Map<?, ?>) {
			sb.append("{"); //$NON-NLS-1$
			boolean prependSeparator = false;
			for (Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) {
				if (prependSeparator) {
					sb.append(", "); //$NON-NLS-1$
				}
				toString(sb, entry.getKey());
				sb.append("="); //$NON-NLS-1$
				toString(sb, entry.getValue());
				prependSeparator = true;
			}
			sb.append("}"); //$NON-NLS-1$
		} else {
			sb.append(object);
		}
	}

	/**
	 * Returns the version of the bundle.
	 * 
	 * @since 3.7
	 * @deprecated use {@link Bundle#getVersion()} instead
	 */
	@Deprecated
	public static Version getVersion(Bundle bundle) {
		return bundle.getVersion();
	}

	/**
	 * Returns true, if <code>o1</code> is equal to <code>o2</code> or <code>o1</code> and <code>o2</code> are
	 * <code>null</code>.
	 * 
	 * @see Object#equals(Object)
	 * @since 3.7
	 */
	public static boolean areEqual(Object o1, Object o2) {
		if (o1 == null) {
			return (o2 == null);
		} else {
			return o1.equals(o2);
		}
	}

	/**
	 * Compares <code>o1</code> and <code>o2</code>.
	 * 
	 * @since 3.7
	 * @return a negative integer, 0, or a positive, if o1 is less than o2, o1 equals o2 or o1 is more than o2; null is
	 *         considered less than any value
	 */
	public static <T> int compare(Comparable<T> o1, T o2) {
		if (o1 == null) {
			return (o2 != null) ? 1 : 0;
		} else if (o2 == null) {
			return -1;
		}
		return o1.compareTo(o2);
	}

	/**
	 * Compares a boolean value.
	 * 
	 * @since 3.7
	 * @see Boolean#equals(Object)
	 */
	public static boolean propertyEquals(boolean value, Object expectedValue) {
		return (expectedValue == null) ? value == true : Boolean.valueOf(value).equals(expectedValue);
	}

	/**
	 * Disables logging through the Apache commons logging system by default. This can be overridden by specifying the
	 * <code>org.apache.commons.logging.Log</code> system property.
	 * 
	 * @since 3.7
	 */
	public static void initializeLoggingSettings() {
		defaultSystemProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Only sets system property if they are not already set to a value.
	 */
	private static void defaultSystemProperty(String key, String defaultValue) {
		if (System.getProperty(key) == null) {
			System.setProperty(key, defaultValue);
		}
	}

	/**
	 * Returns the version of the Java runtime.
	 * 
	 * @since 3.7
	 * @return {@link Version#emptyVersion} if the version can not be determined
	 */
	public static Version getRuntimeVersion() {
		Version result = parseRuntimeVersion(System.getProperty("java.runtime.version")); //$NON-NLS-1$
		if (result == Version.emptyVersion) {
			result = parseRuntimeVersion(System.getProperty("java.version")); //$NON-NLS-1$
		}
		return result;
	}

	private static Version parseRuntimeVersion(String versionString) {
		if (versionString != null) {
			int firstSeparator = versionString.indexOf('.');
			if (firstSeparator != -1) {
				try {
					int secondSeparator = versionString.indexOf('.', firstSeparator + 1);
					if (secondSeparator != -1) {
						int index = findLastNumberIndex(versionString, secondSeparator);
						String qualifier = versionString.substring(index + 1);
						if (qualifier.startsWith("_") && qualifier.length() > 1) { //$NON-NLS-1$
							versionString = versionString.substring(0, index + 1) + "." + qualifier.substring(1); //$NON-NLS-1$
						} else {
							versionString = versionString.substring(0, index + 1);
						}
						return new Version(versionString);
					}
					return new Version(versionString.substring(0,
							findLastNumberIndex(versionString, firstSeparator) + 1));
				} catch (IllegalArgumentException e) {
					// ignore
				}
			}
		}
		return Version.emptyVersion;
	}

	private static int findLastNumberIndex(String versionString, int secondSeparator) {
		int lastDigit = secondSeparator;
		for (int i = secondSeparator + 1; i < versionString.length(); i++) {
			if (Character.isDigit(versionString.charAt(i))) {
				lastDigit++;
			} else {
				break;
			}
		}
		if (lastDigit == secondSeparator) {
			return secondSeparator - 1;
		}
		return lastDigit;
	}

	/**
	 * Returns the running Mylyn version without the qualifier.
	 * 
	 * @since 3.7
	 */
	public static Version getFrameworkVersion() {
		return new Version(FRAMEWORK_VERSION);
	}

	/**
	 * Returns a representation of <code>name</code> that is a valid file name.
	 * 
	 * @since 3.7
	 */
	public static String asFileName(String name) {
		StringBuffer sb = new StringBuffer(name.length());
		char[] chars = name.toCharArray();
		for (char c : chars) {
			if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '.') {
				sb.append(c);
			} else {
				sb.append("%" + Integer.toHexString(c).toUpperCase()); //$NON-NLS-1$
			}
		}
		return sb.toString();
	}

	/**
	 * Returns the decoded form of <code>text</code>.
	 * 
	 * @since 3.8
	 * @see #encode(String)
	 * @throws IllegalArgumentException
	 *             if text is not in a valid form, i.e. it was not encoded using {@link CoreUtil#encode(String)}
	 */
	public static String decode(String text) {
		boolean escaped = false;
		StringBuilder sb = new StringBuilder(text.length());
		StringBuilder escapedText = new StringBuilder(4);
		char[] chars = text.toCharArray();
		for (char c : chars) {
			if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '.') {
				if (escaped) {
					escapedText.append(c);
				} else {
					sb.append(c);
				}
			} else if (c == '%') {
				if (escaped) {
					throw new IllegalArgumentException("Unexpected '%' sign in '" + text + "'"); //$NON-NLS-1$ //$NON-NLS-2$
				}
				escaped = !escaped;
			} else if (c == '_') {
				if (!escaped) {
					throw new IllegalArgumentException("Unexpected '_' sign in '" + text + "'"); //$NON-NLS-1$ //$NON-NLS-2$
				}
				try {
					sb.append((char) Integer.parseInt(escapedText.toString(), 16));
					escapedText.setLength(0);
				} catch (NumberFormatException e) {
					throw new IllegalArgumentException("Invalid escape code in '" + text + "'"); //$NON-NLS-1$ //$NON-NLS-2$
				}
				escaped = !escaped;
			} else {
				throw new IllegalArgumentException("Unexpected character '" + c + "' in '" + text + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
		}
		return sb.toString();
	}

	/**
	 * An encoded form of <code>text</code> that is suitable as a filename.
	 * 
	 * @param text
	 *            the string to encode
	 * @see #decode(String)
	 * @since 3.8
	 */
	public static String encode(String text) {
		StringBuilder sb = new StringBuilder(text.length());
		char[] chars = text.toCharArray();
		for (char c : chars) {
			if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '.') {
				sb.append(c);
			} else {
				sb.append("%"); //$NON-NLS-1$
				sb.append(Integer.toHexString(c).toUpperCase());
				sb.append("_"); //$NON-NLS-1$
			}
		}
		return sb.toString();
	}

	/**
	 * Returns a new {@link XMLReader} instance using default factories.
	 * 
	 * @since 3.9
	 */
	public static SAXParser newSaxParser() throws SAXException {
		try {
			return saxParserFactory.newSAXParser();
		} catch (ParserConfigurationException e) {
			throw new SAXException(e);
		}
	}

	/**
	 * Returns a new {@link XMLReader} instance using default factories.
	 * 
	 * @since 3.9
	 */
	public static XMLReader newXmlReader() throws SAXException {
		return newSaxParser().getXMLReader();
	}

}
