/*******************************************************************************
 * Copyright (c) 2007, 2010 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 API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.frameworkadmin.utils;

import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
import org.eclipse.osgi.service.pluginconversion.PluginConverter;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;

public class Utils {
	private static final String FEATURE_MANIFEST = "feature.xml"; //$NON-NLS-1$
	private static final String FILE_SCHEME = "file"; //$NON-NLS-1$
	private static final String FRAGMENT_MANIFEST = "fragment.xml"; //$NON-NLS-1$
	private static final String PATH_SEP = "/"; //$NON-NLS-1$
	private static final String PLUGIN_MANIFEST = "plugin.xml"; //$NON-NLS-1$

	/**
	 * Overwrite all properties of from to the properties of to. Return the result of to.
	 * 
	 * @param to Properties whose keys and values of other Properties will be appended to.
	 * @param from Properties whose keys and values will be set to the other properties.
	 * @return Properties as a result of this method. 
	 */
	public static Properties appendProperties(Properties to, Properties from) {
		if (from != null) {
			if (to == null)
				to = new Properties();
			//			printoutProperties(System.out, "to", to);
			//			printoutProperties(System.out, "from", from);

			for (Enumeration enumeration = from.keys(); enumeration.hasMoreElements();) {
				String key = (String) enumeration.nextElement();
				to.setProperty(key, from.getProperty(key));
			}
		}
		//		printoutProperties(System.out, "to", to);
		return to;
	}

	//Return a dictionary representing a manifest. The data may result from plugin.xml conversion  
	private static Dictionary basicLoadManifest(File bundleLocation) {
		InputStream manifestStream = null;
		ZipFile jarFile = null;
		try {
			try {
				// Handle a JAR'd bundle
				if (bundleLocation.isFile()) {
					jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ);
					ZipEntry manifestEntry = jarFile.getEntry(JarFile.MANIFEST_NAME);
					if (manifestEntry != null) {
						manifestStream = jarFile.getInputStream(manifestEntry);
					}
				} else {
					// we have a directory-based bundle
					File bundleManifestFile = new File(bundleLocation, JarFile.MANIFEST_NAME);
					if (bundleManifestFile.exists())
						manifestStream = new BufferedInputStream(new FileInputStream(new File(bundleLocation, JarFile.MANIFEST_NAME)));
				}
			} catch (IOException e) {
				//ignore
			}
			// we were unable to get an OSGi manifest file so try and convert an old-style manifest
			if (manifestStream == null)
				return convertPluginManifest(bundleLocation, true);

			try {
				Map manifest = ManifestElement.parseBundleManifest(manifestStream, null);
				// add this check to handle the case were we read a non-OSGi manifest
				if (manifest.get(Constants.BUNDLE_SYMBOLICNAME) == null)
					return convertPluginManifest(bundleLocation, true);
				return manifestToProperties(manifest);
			} catch (IOException ioe) {
				return null;
			} catch (BundleException e) {
				return null;
			}
		} finally {
			try {
				if (manifestStream != null)
					manifestStream.close();
			} catch (IOException e1) {
				//Ignore
			}
			try {
				if (jarFile != null)
					jarFile.close();
			} catch (IOException e2) {
				//Ignore
			}
		}
	}

	public static void checkAbsoluteDir(File file, String dirName) throws IllegalArgumentException {
		if (file == null)
			throw new IllegalArgumentException(dirName + " is null");
		if (!file.isAbsolute())
			throw new IllegalArgumentException(dirName + " is not absolute path. file=" + file.getAbsolutePath());
		if (!file.isDirectory())
			throw new IllegalArgumentException(dirName + " is not directory. file=" + file.getAbsolutePath());
	}

	public static void checkAbsoluteFile(File file, String dirName) {//throws ManipulatorException {
		if (file == null)
			throw new IllegalArgumentException(dirName + " is null");
		if (!file.isAbsolute())
			throw new IllegalArgumentException(dirName + " is not absolute path. file=" + file.getAbsolutePath());
		if (file.isDirectory())
			throw new IllegalArgumentException(dirName + " is not file but directory");
	}

	public static URL checkFullUrl(URL url, String urlName) throws IllegalArgumentException {//throws ManipulatorException {
		if (url == null)
			throw new IllegalArgumentException(urlName + " is null");
		if (!url.getProtocol().endsWith("file")) //$NON-NLS-1$
			return url;
		File file = new File(url.getFile());
		if (!file.isAbsolute())
			throw new IllegalArgumentException(urlName + "(" + url + ") does not have absolute path");
		if (file.getAbsolutePath().startsWith(PATH_SEP))
			return url;
		try {
			return getUrl("file", null, PATH_SEP + file.getAbsolutePath()); //$NON-NLS-1$
		} catch (MalformedURLException e) {
			throw new IllegalArgumentException(urlName + "(" + "file:" + PATH_SEP + file.getAbsolutePath() + ") is not fully quallified");
		}
	}

	/*
	 * Copied from BundleDescriptionFactory in the metadata generator.
	 */
	private static Dictionary convertPluginManifest(File bundleLocation, boolean logConversionException) {
		PluginConverter converter;
		try {
			converter = org.eclipse.equinox.internal.frameworkadmin.utils.Activator.acquirePluginConverter();
			if (converter == null) {
				new RuntimeException("Unable to aquire PluginConverter service during generation for: " + bundleLocation).printStackTrace(); //$NON-NLS-1$
				return null;
			}
			return converter.convertManifest(bundleLocation, false, null, true, null);
		} catch (PluginConversionException convertException) {
			// only log the exception if we had a plugin.xml or fragment.xml and we failed conversion
			if (bundleLocation.getName().equals(FEATURE_MANIFEST))
				return null;
			if (!new File(bundleLocation, PLUGIN_MANIFEST).exists() && !new File(bundleLocation, FRAGMENT_MANIFEST).exists())
				return null;
			if (logConversionException) {
				IStatus status = new Status(IStatus.WARNING, "org.eclipse.equinox.frameworkadmin", 0, "Error converting bundle manifest.", convertException);
				System.out.println(status);
				//TODO Need to find a way to get a logging service to log
			}
			return null;
		}
	}

	public static boolean createParentDir(File file) {
		File parent = file.getParentFile();
		if (parent == null)
			return false;
		if (parent.exists())
			return true;
		return parent.mkdirs();
	}

	public static BundleInfo[] getBundleInfosFromList(List list) {
		if (list == null)
			return new BundleInfo[0];
		BundleInfo[] ret = new BundleInfo[list.size()];
		list.toArray(ret);
		return ret;
	}

	public static String[] getClauses(String header) {
		StringTokenizer token = new StringTokenizer(header, ","); //$NON-NLS-1$
		List list = new LinkedList();
		while (token.hasMoreTokens()) {
			list.add(token.nextToken());
		}
		String[] ret = new String[list.size()];
		list.toArray(ret);
		return ret;
	}

	public static String[] getClausesManifestMainAttributes(URI location, String name) {
		return getClauses(getManifestMainAttributes(location, name));
	}

	public static String getManifestMainAttributes(URI location, String name) {
		Dictionary manifest = Utils.getOSGiManifest(location);
		if (manifest == null)
			throw new RuntimeException("Unable to locate bundle manifest: " + location);
		return (String) manifest.get(name);
	}

	public static Dictionary getOSGiManifest(URI location) {
		if (location == null)
			return null;
		// if we have a file-based URL that doesn't end in ".jar" then...
		if (FILE_SCHEME.equals(location.getScheme()))
			return basicLoadManifest(URIUtil.toFile(location));

		try {
			URL url = new URL("jar:" + location.toString() + "!/"); //$NON-NLS-1$//$NON-NLS-2$
			JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
			ZipFile jar = jarConnection.getJarFile();

			try {
				ZipEntry entry = jar.getEntry(JarFile.MANIFEST_NAME);
				if (entry == null)
					return null;

				Map manifest = ManifestElement.parseBundleManifest(jar.getInputStream(entry), null);
				// if we have a JAR'd bundle that has a non-OSGi manifest file (like
				// the ones produced by Ant, then try and convert the plugin.xml
				if (manifest.get(Constants.BUNDLE_SYMBOLICNAME) == null) {
					String jarName = jar.getName();
					File file = jarName != null ? new File(jarName) : null;
					if (file != null && file.exists()) {
						return convertPluginManifest(file, true);
					}
					return null;
				}
				return manifestToProperties(manifest);
			} catch (BundleException e) {
				return null;
			} finally {
				jar.close();
			}
		} catch (IOException e) {
			if (System.getProperty("osgi.debug") != null) {
				System.err.println("location=" + location);
				e.printStackTrace();
			}
		}
		return null;
	}

	public static String getPathFromClause(String clause) {
		if (clause == null)
			return null;
		if (clause.indexOf(";") != -1)
			clause = clause.substring(0, clause.indexOf(";"));
		return clause.trim();
	}

	public static String getRelativePath(File target, File from) {

		String targetPath = Utils.replaceAll(target.getAbsolutePath(), File.separator, PATH_SEP);
		String fromPath = Utils.replaceAll(from.getAbsolutePath(), File.separator, PATH_SEP);

		String[] targetTokens = Utils.getTokens(targetPath, PATH_SEP);
		String[] fromTokens = Utils.getTokens(fromPath, PATH_SEP);
		int index = -1;
		for (int i = 0; i < fromTokens.length; i++)
			if (fromTokens[i].equals(targetTokens[i]))
				index = i;
			else
				break;

		StringBuffer sb = new StringBuffer();
		for (int i = index + 1; i < fromTokens.length; i++)
			sb.append(".." + PATH_SEP);

		for (int i = index + 1; i < targetTokens.length; i++)
			if (i != targetTokens.length - 1)
				sb.append(targetTokens[i] + PATH_SEP);
			else
				sb.append(targetTokens[i]);
		return sb.toString();
	}

	/**
	 * This method will be called for create a backup file.
	 * 
	 * @param file target file
	 * @return File backup file whose filename consists of "hogehoge.yyyyMMddHHmmss.ext" or 
	 * 	"hogehoge.yyyyMMddHHmmss".
	 */
	public static File getSimpleDataFormattedFile(File file) {
		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); //$NON-NLS-1$
		String date = df.format(new Date());
		String filename = file.getName();
		int index = filename.lastIndexOf("."); //$NON-NLS-1$
		if (index != -1)
			filename = filename.substring(0, index) + "." + date + "." + filename.substring(index + 1); //$NON-NLS-1$ //$NON-NLS-2$
		else
			filename = filename + "." + date; //$NON-NLS-1$
		File dest = new File(file.getParentFile(), filename);
		return dest;
	}

	public static String[] getTokens(String msg, String delim) {
		return getTokens(msg, delim, false);
	}

	public static String[] getTokens(String msg, String delim, boolean returnDelims) {
		StringTokenizer targetST = new StringTokenizer(msg, delim, returnDelims);
		String[] tokens = new String[targetST.countTokens()];
		ArrayList list = new ArrayList(targetST.countTokens());
		while (targetST.hasMoreTokens()) {
			list.add(targetST.nextToken());
		}
		list.toArray(tokens);
		return tokens;
	}

	public static URL getUrl(String protocol, String host, String file) throws MalformedURLException {// throws ManipulatorException {
		file = Utils.replaceAll(file, File.separator, "/");
		return new URL(protocol, host, file);
	}

	public static URL getUrlInFull(String path, URL from) throws MalformedURLException {//throws ManipulatorException {
		Utils.checkFullUrl(from, "from");
		path = Utils.replaceAll(path, File.separator, "/"); //$NON-NLS-1$
		//System.out.println("from.toExternalForm()=" + from.toExternalForm());
		String fromSt = Utils.removeLastCh(from.toExternalForm(), '/');
		//System.out.println("fromSt=" + fromSt);
		if (path.startsWith("/")) { //$NON-NLS-1$
			String fileSt = from.getFile();
			return new URL(fromSt.substring(0, fromSt.lastIndexOf(fileSt) - 1) + path);
		}
		return new URL(fromSt + "/" + path); //$NON-NLS-1$
	}

	private static Properties manifestToProperties(Map d) {
		Iterator iter = d.keySet().iterator();
		Properties result = new Properties();
		while (iter.hasNext()) {
			String key = (String) iter.next();
			result.put(key, d.get(key));
		}
		return result;
	}

	/**
	 * Just used for debug.
	 * 
	 * @param ps printstream
	 * @param name name of properties 
	 * @param props properties whose keys and values will be printed out.
	 */
	public static void printoutProperties(PrintStream ps, String name, Properties props) {
		if (props == null || props.size() == 0) {
			ps.println("Props(" + name + ") is empty");
			return;
		}
		ps.println("Props(" + name + ")=");
		for (Enumeration enumeration = props.keys(); enumeration.hasMoreElements();) {
			String key = (String) enumeration.nextElement();
			ps.print("\tkey=" + key);
			ps.println("\tvalue=" + props.getProperty(key));
		}
	}

	public static String removeLastCh(String target, char ch) {
		while (target.charAt(target.length() - 1) == ch) {
			target = target.substring(0, target.length() - 1);
		}
		return target;
	}

	public static String replaceAll(String st, String oldSt, String newSt) {
		if (oldSt.equals(newSt))
			return st;
		int index = -1;
		while ((index = st.indexOf(oldSt)) != -1) {
			st = st.substring(0, index) + newSt + st.substring(index + oldSt.length());
		}
		return st;
	}

	/**
	 * Sort by increasing order of startlevels.
	 * 
	 * @param bInfos array of BundleInfos to be sorted.
	 * @param initialBSL initial bundle start level to be used.
	 * @return sorted array of BundleInfos
	 */
	public static BundleInfo[] sortBundleInfos(BundleInfo[] bInfos, int initialBSL) {
		SortedMap bslToList = new TreeMap();
		for (int i = 0; i < bInfos.length; i++) {
			Integer sL = new Integer(bInfos[i].getStartLevel());
			if (sL.intValue() == BundleInfo.NO_LEVEL)
				sL = new Integer(initialBSL);
			List list = (List) bslToList.get(sL);
			if (list == null) {
				list = new LinkedList();
				bslToList.put(sL, list);
			}
			list.add(bInfos[i]);
		}

		// bslToList is sorted by the key (StartLevel).
		List bundleInfoList = new LinkedList();
		for (Iterator ite = bslToList.keySet().iterator(); ite.hasNext();) {
			Integer sL = (Integer) ite.next();
			List list = (List) bslToList.get(sL);
			for (Iterator ite2 = list.iterator(); ite2.hasNext();) {
				BundleInfo bInfo = (BundleInfo) ite2.next();
				bundleInfoList.add(bInfo);
			}
		}
		return getBundleInfosFromList(bundleInfoList);
	}

	/**
	 * get String representing the given properties.
	 * 
	 * @param name name of properties 
	 * @param props properties whose keys and values will be printed out.
	 */
	public static String toStringProperties(String name, Properties props) {
		if (props == null || props.size() == 0) {
			return "Props(" + name + ") is empty\n";
		}
		StringBuffer sb = new StringBuffer();
		sb.append("Props(" + name + ") is \n");
		for (Enumeration enumeration = props.keys(); enumeration.hasMoreElements();) {
			String key = (String) enumeration.nextElement();
			sb.append("\tkey=" + key + "\tvalue=" + props.getProperty(key) + "\n");
		}
		return sb.toString();
	}

}
