//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.epf.common.preferences.IPreferenceStoreWrapper;
import org.eclipse.epf.common.serviceability.Logger;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.I18nUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

/**
 * The abstract base class for all EPF plug-ins.
 * 
 * @author Kelvin Low
 * @author Jinhua Xi
 * @author Phong Nguyen Le
 * @since 1.0
 */
public abstract class AbstractActivator extends Plugin implements IActivator {

	// The relative path to the icons.
	private static final String ICON_PATH = "icons/"; //$NON-NLS-1$;

	// The logger hash map.
	private static Map<String, Logger> loggers = new HashMap<String, Logger>();

	// The message dialog hash map.
	//private static Map<String, MsgDialog> msgDialogs = new HashMap<String, MsgDialog>();

	// The shared image hash map.
	//private static Map<String, Image> sharedImages = new HashMap<String, Image>();

	// The resource bundle for this plug-in.
	private ResourceBundle resourceBundle;

	// This plug-in ID.
	private String pluginId;

	// The plug-in install URL.
	private URL installURL;

	// The plug-in install path.
	private String installPath;

	// The plug-in icon URL.
	protected URL iconURL;

	// The profiling flag.
	private boolean profiling;
	
	private Map<String, Boolean> debugMap = new HashMap<String, Boolean>();

	/**
	 * Default constructor.
	 */
	public AbstractActivator() {
		super();
	}

	/**
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(BundleContext)
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);

		init(context);

		// set the 
		if (isDebugging()) {
			getLogger().logInfo("Started " + pluginId); //$NON-NLS-1$			
		}
	}

	/**
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		// Free the shared images.
//		for (Iterator images = sharedImages.values().iterator(); images
//				.hasNext();) {
//			Image image = (Image) images.next();
//			if (image != null && !image.isDisposed()) {
//				image.dispose();
//			}
//		}

		super.stop(context);

		if (isDebugging()) {
			getLogger().logInfo("Stopped " + pluginId); //$NON-NLS-1$
		}
	}

	/**
	 * Initializes this plug-in.
	 * 
	 * @param context
	 *            The bundle context.
	 */
	protected void init(BundleContext context) throws Exception {
		// Get the bundle for this plug-in.
		Bundle bundle = getBundle();

		// Get the resouce bundle for this plug-in.
		resourceBundle = Platform.getResourceBundle(bundle);

		// Get the ID for this plug-in.
		pluginId = bundle.getSymbolicName();

		if (isDebugging()) {
			getLogger().logInfo("Initializing " + pluginId); //$NON-NLS-1$		
		}

		// Get the install path of this plug-in.
		installURL = bundle.getEntry("/"); //$NON-NLS-1$

		try {
			installPath = FileLocator.resolve(installURL).getPath();
		} catch (IOException e) {
			installPath = Platform.getInstallLocation().getURL().getPath();
		}

		try {
			iconURL = new URL(installURL, ICON_PATH);
		} catch (IOException e) {
		}

		String symbolicName = bundle.getSymbolicName();
		if (symbolicName != null) {
			String key = symbolicName + "/profiling"; //$NON-NLS-1$
			String value = Platform.getDebugOption(key);
			profiling = value == null ? false : value.equalsIgnoreCase("true"); //$NON-NLS-1$
		}

		if (isDebugging()) {
			getLogger().logInfo(
					"Initialized " + pluginId + ", installPath=" + installPath); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}
	
	public boolean debug(String debugType) {
		Boolean b = debugMap.get(debugType);
		if (b == null) {
			Bundle bundle = getBundle();
			String symbolicName = bundle.getSymbolicName();
			if (symbolicName != null) {
				String key = symbolicName + "/" + debugType; //$NON-NLS-1$
				String value = Platform.getDebugOption(key);
				boolean bValue = value == null ? false : value.equalsIgnoreCase("true"); //$NON-NLS-1$
				b = new Boolean(bValue);
				debugMap.put(debugType, b);
			}
		}		
		return b.booleanValue();
	}

	/**
	 * Returns the ID of this plug-in.
	 * 
	 * @return The ID of this plug-in.
	 */
	public String getId() {
		return pluginId;
	}

	/**
	 * Returns the install URL of this plug-in.
	 * 
	 * @param The
	 *            install URL of this plug-in.
	 */
	public URL getInstallURL() {
		return installURL;
	}

	/**
	 * Returns the install path of this plug-in.
	 * 
	 * @param The
	 *            install path of this plug-in.
	 */
	public String getInstallPath() {
		return installPath;
	}

	/**
	 * Loads and returns the localized properties of a Java properties file.
	 * <p>
	 * 
	 * @param path
	 *            The properties file path relative to the plug-in root.
	 * @return A <code>Properties</code> object.
	 */
	public Properties getProperties(String path) throws IOException {
		Properties props = new Properties();
		if (path == null) {
			return props;
		}

		String filePath = getLocalizedFile(path, true);
		if (filePath != null) {
			props.load(new FileInputStream(filePath));
		}

		return props;
	}

	/**
	 * get the locale specific absolute file path name of the given file in the
	 * plugin.
	 * 
	 * @param path
	 *            The properties file path relative to the plug-in root.
	 * @return String the locale specific absolute file path name of the given
	 *         file.
	 * @throws IOException
	 */
	public String getLocalizedFile(String path, boolean useDefault)
			throws IOException {
		String filePath = null;
		String fileName = FileUtil.getFileName(path);
		int index = path.lastIndexOf(fileName);
		String pathName = path.substring(0, index);

		Locale locale = Locale.getDefault();

		Bundle bundle = getBundle();
		Bundle[] bundles = Platform.getFragments(bundle);
		if (bundles != null) {
			for (int i = 0; i < bundles.length; i++) {
				URL entry = bundles[i].getEntry(pathName);
				if (entry != null) {
					URL url = FileLocator.resolve(entry);
					filePath = I18nUtil.getLocalizedFile(url.getPath()
							+ fileName, locale); 
					if (filePath != null) {
						break;
					}
				}
			}
		}

		if (filePath == null) {
			URL entry = bundle.getEntry(path);
			if (entry != null) {
				URL url = FileLocator.resolve(entry);
				filePath = I18nUtil.getLocalizedFile(url.getPath(), locale);
				if (filePath == null && useDefault) {
					filePath = url.getPath();
				}
			}
		}

		return filePath;
	}

	/**
	 * for the given path in the plugin, find the localized files form the nl
	 * fragemenets and copy the localized files to the destination folder
	 * 
	 * @param path
	 *            String a relative path to the plugin root. The files in this
	 *            folder will be iterated and their localized files will be
	 *            copied over
	 * @param toDir
	 *            FIle the destination folder
	 * @param recursive
	 *            boolean recurively looking for files int the specified folder
	 * @param useLocaleFileName
	 *            boolean if true the locale specific file names will be used in
	 *            the copied destination, otherwise, the locale specific file
	 *            name will be renamed to the default one in the destination
	 *            folder
	 * @throws IOException
	 */
	public void copyLocalizedFiles(String path, File toDir, boolean recursive,
			boolean useLocaleFileName) throws IOException {
		String pluginPath = getInstallPath();
		URI pluginUri = new File(pluginPath).toURI();
		URI pathUri = new File(pluginPath, path).toURI();

		List<File> files = new ArrayList<File>();
		File f = new File(pluginPath, path);
		FileUtil.getAllFiles(f, files, recursive);

		// for each file found in the specified folder, get the localized file
		for (Iterator it = files.iterator(); it.hasNext();) {
			URI srcUri = ((File) it.next()).toURI();

			// get the relative path of the file to the plugin root, then find
			// the localized file
			String relPath = pluginUri.relativize(srcUri).getPath();

			// only get the locale specific file, don't include the default one
			String localizedFile = getLocalizedFile(relPath, false);
			if (localizedFile == null) {
				continue;
			}

			// need to change the target file path to relative to the path
			// instead of the plugin root
			relPath = pathUri.relativize(srcUri).getPath();
			File srcFile = new File(localizedFile);
			File targetFile = new File(toDir, relPath);
			File targetParent = targetFile.getParentFile();

			// copy the file to the desitination
			// if useLocaleFileName is true, the destination file name should
			// also use the locale specific file name
			if (useLocaleFileName) {
				String fileName = srcFile.getName();
				targetFile = new File(targetParent, fileName);
			}

			if (isDebugging()) {
				System.out.println("Copying localized file: "); //$NON-NLS-1$
				System.out.println("Source: " + srcFile); //$NON-NLS-1$
				System.out.println("Target: " + targetFile); //$NON-NLS-1$
				System.out.println(""); //$NON-NLS-1$
			}

			try {
				if (!targetParent.exists()) {
					targetParent.mkdirs();
				}

				if (!targetFile.exists()) {
					targetFile.createNewFile();
				}

				FileUtil.copyFile(srcFile, targetFile);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	/**
	 * Returns the localized resource.
	 * 
	 * @param key
	 *            The resource key.
	 * @return The localized resource.
	 */
	public String getString(String key) {
		if (resourceBundle != null) {
			try {
				return resourceBundle.getString(key);
			} catch (MissingResourceException e) {
			}
		}
		return '[' + key + ']';
	}

	/**
	 * Returns the formatted localized message given the resource key and the
	 * message argument.
	 * 
	 * @param key
	 *            The resource key.
	 * @param argument
	 *            The message argument.
	 * @return The formatted localized message.
	 */
	public String formatMessage(String key, Object argument) {
		if (resourceBundle != null) {
			try {
				String msg = resourceBundle.getString(key);
				Object[] arguments = { argument };
				return MessageFormat.format(msg, arguments);
			} catch (MissingResourceException e) {
			}
		}
		return '[' + key + ']';
	}

	/**
	 * Returns the image URL given the relative path.
	 * 
	 * @param relativePath
	 *            The image's path relative to the plug-in's root.
	 * @return The image URL.
	 */
	public URL getImageURL(String relativePath) {
		try {
			URL url = new URL(iconURL, relativePath);
			return FileLocator.resolve(url);
		} catch (Exception e) {
			return null;
		}
	}

//	/**
//	 * Returns the image descriptor given the relative path.
//	 * 
//	 * @param relativePath
//	 *            The image's path relative to the plug-in's root.
//	 * @return The image descriptor.
//	 */
//	public ImageDescriptor getImageDescriptor(String relativePath) {
//		try {
//			URL url = new URL(iconURL, relativePath);
//			return ImageDescriptor.createFromURL(url);
//		} catch (MalformedURLException e) {
//			return ImageDescriptor.getMissingImageDescriptor();
//		}
//	}
//
//	/**
//	 * Returns the image given the relative path.
//	 * <p>
//	 * Note: The returned image need to be freed by the caller.
//	 * 
//	 * @param relativePath
//	 *            The image's path relative to the plug-in's root.
//	 * @return The image.
//	 */
//	public Image getImage(String relativePath) {
//		Image image = null;
//
//		ImageDescriptor imageDescriptor = getImageDescriptor(relativePath);
//		if (imageDescriptor != null) {
//			image = imageDescriptor.createImage(false);
//		}
//
//		return image;
//	}
//
//	/**
//	 * Returns the shared image given the relative path.
//	 * <p>
//	 * Note: The returned image will be automatically freed when the plug-in
//	 * shuts down.
//	 * 
//	 * @param relativePath
//	 *            The image's path relative to the plug-in's root.
//	 * @return The image.
//	 */
//	public Image getSharedImage(String relativePath) {
//		Image image = (Image) sharedImages.get(relativePath);
//		if (image != null) {
//			return image;
//		}
//
//		ImageDescriptor imageDescriptor = getImageDescriptor(relativePath);
//		if (imageDescriptor != null) {
//			image = imageDescriptor.createImage(false);
//			if (image != null) {
//				sharedImages.put(relativePath, image);
//			}
//		}
//
//		return image;
//	}

	/**
	 * Returns the profiling flag.
	 * 
	 * @return <code>true</code> if profiling is enabled for this plu-in
	 */
	public boolean isProfiling() {
		return profiling;
	}

	/**
	 * Returns the logger given the plug-in ID.
	 * 
	 * @return The new or cached logger.
	 */
	public Logger getLogger() {
		Logger logger = (Logger) loggers.get(pluginId);
		if (logger == null) {
			logger = new Logger(this);
			loggers.put(pluginId, logger);
		}
		return logger;
	}
		
	/**
	 * Logs the given object or message.
	 */
	public void log(Object logEntry) {
		if (logEntry instanceof Throwable) {
			((Throwable) logEntry).printStackTrace(System.err);
		} else {
			System.err.println(logEntry);
		}
	}
	
	public IPreferenceStoreWrapper getPreferenceStore() {
		return CommonPlugin.getDefault().getCommonPreferenceStore();
	}
	
	
	public Object getContext() {
		if ( CommonPlugin.getDefault().contextProvider != null ) {
			return CommonPlugin.getDefault().contextProvider.getContext();
		}
		
		return null;
	}
	
	public IMessageCallback getMsgCallback() {
		return CommonPlugin.getDefault().msgCallback;
	}
}
