/*******************************************************************************
 * Copyright (c) 2000, 2017 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.team.internal.ui;

import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.*;

import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.debug.DebugOptionsListener;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.RepositoryProviderType;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.internal.ui.mapping.StreamMergerDelegate;
import org.eclipse.team.internal.ui.mapping.WorkspaceTeamStateProvider;
import org.eclipse.team.internal.ui.synchronize.SynchronizeManager;
import org.eclipse.team.internal.ui.synchronize.TeamSynchronizingPerspective;
import org.eclipse.team.internal.ui.synchronize.actions.GlobalRefreshAction;
import org.eclipse.team.ui.ISharedImages;
import org.eclipse.team.ui.mapping.ITeamStateProvider;
import org.eclipse.team.ui.synchronize.*;
import org.eclipse.ui.*;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.*;

/**
 * TeamUIPlugin is the plugin for generic, non-provider specific,
 * team UI functionality in the workbench.
 */
public class TeamUIPlugin extends AbstractUIPlugin {

	private static TeamUIPlugin instance;

	// image paths
	public static final String ICON_PATH = "$nl$/icons/full/"; //$NON-NLS-1$

	public static final String ID = "org.eclipse.team.ui"; //$NON-NLS-1$

	// plugin id
	public static final String PLUGIN_ID = "org.eclipse.team.ui"; //$NON-NLS-1$

	public static final String TRIGGER_POINT_ID = "org.eclipse.team.ui.activityTriggerPoint"; //$NON-NLS-1$

	private static List<IPropertyChangeListener> propertyChangeListeners = new ArrayList<IPropertyChangeListener>(5);

	private Hashtable<String, ImageDescriptor> imageDescriptors = new Hashtable<String, ImageDescriptor>(20);

	private WorkspaceTeamStateProvider provider;

	private Map<String, TeamStateProvider> decoratedStateProviders = new HashMap<String, TeamStateProvider>();

	// manages synchronize participants
	private SynchronizeManager synchronizeManager;

	private ServiceRegistration<DebugOptionsListener> debugRegistration;

	/**
	 * ID of the 'Remove from View' action.
	 * Value: <code>"org.eclipse.team.internal.ui.RemoveFromView"</code>
	 */
	public static final String REMOVE_FROM_VIEW_ACTION_ID = "org.eclipse.team.internal.ui.RemoveFromView"; //$NON-NLS-1$


	/**
	 * Creates a new TeamUIPlugin.
	 */
	public TeamUIPlugin() {
		super();
		instance = this;
	}

	/**
	 * Creates an extension.  If the extension plugin has not
	 * been loaded a busy cursor will be activated during the duration of
	 * the load.
	 *
	 * @param element the config element defining the extension
	 * @param classAttribute the name of the attribute carrying the class
	 * @return the extension object
	 * @throws CoreException
	 */
	public static Object createExtension(final IConfigurationElement element, final String classAttribute) throws CoreException {
		// If plugin has been loaded create extension.
		// Otherwise, show busy cursor then create extension.
		Bundle bundle = Platform.getBundle(element.getNamespaceIdentifier());
		if (bundle.getState() == org.osgi.framework.Bundle.ACTIVE) {
			return element.createExecutableExtension(classAttribute);
		} else {
			final Object [] ret = new Object[1];
			final CoreException [] exc = new CoreException[1];
			BusyIndicator.showWhile(null, () -> {
				try {
					ret[0] = element.createExecutableExtension(classAttribute);
				} catch (CoreException e) {
					exc[0] = e;
				}
			});
			if (exc[0] != null)
				throw exc[0];
			else
				return ret[0];
		}
	}

	/**
	 * Convenience method to get the currently active workbench page. Note that
	 * the active page may not be the one that the usr perceives as active in
	 * some situations so this method of obtaining the activae page should only
	 * be used if no other method is available.
	 *
	 * @return the active workbench page
	 */
	public static IWorkbenchPage getActivePage() {
		IWorkbenchWindow window = getPlugin().getWorkbench().getActiveWorkbenchWindow();
		if (window == null) return null;
		return window.getActivePage();
	}

	/**
	 * Return the default instance of the receiver. This represents the runtime plugin.
	 *
	 * @return the singleton plugin instance
	 */
	public static TeamUIPlugin getPlugin() {
		return instance;
	}
	/**
	 * Initializes the preferences for this plugin if necessary.
	 */
	@Override
	protected void initializeDefaultPluginPreferences() {
		IPreferenceStore store = getPreferenceStore();
		store.setDefault(IPreferenceIds.SYNCVIEW_VIEW_SYNCINFO_IN_LABEL, false);
		store.setDefault(IPreferenceIds.SHOW_AUTHOR_IN_COMPARE_EDITOR, false);
		store.setDefault(IPreferenceIds.MAKE_FILE_WRITTABLE_IF_CONTEXT_MISSING, false);
		store.setDefault(IPreferenceIds.REUSE_OPEN_COMPARE_EDITOR, true);
		store.setDefault(IPreferenceIds.RUN_IMPORT_IN_BACKGROUND, false);
		store.setDefault(IPreferenceIds.APPLY_PATCH_IN_SYNCHRONIZE_VIEW, false);
		store.setDefault(IPreferenceIds.SYNCVIEW_COMPRESS_FOLDERS, true);
		store.setDefault(IPreferenceIds.SYNCVIEW_DEFAULT_LAYOUT, IPreferenceIds.COMPRESSED_LAYOUT);
		store.setDefault(IPreferenceIds.SYNCVIEW_DEFAULT_PERSPECTIVE, TeamSynchronizingPerspective.ID);
		store.setDefault(IPreferenceIds.SYNCHRONIZING_DEFAULT_PARTICIPANT, GlobalRefreshAction.NO_DEFAULT_PARTICPANT);
		store.setDefault(IPreferenceIds.SYNCHRONIZING_DEFAULT_PARTICIPANT_SEC_ID, GlobalRefreshAction.NO_DEFAULT_PARTICPANT);
		store.setDefault(IPreferenceIds.SYNCHRONIZING_COMPLETE_PERSPECTIVE, MessageDialogWithToggle.PROMPT);
		store.setDefault(IPreferenceIds.SYNCVIEW_REMOVE_FROM_VIEW_NO_PROMPT, false);
		store.setDefault(IPreferenceIds.PREF_WORKSPACE_FIRST_TIME, true);

		// Convert the old compressed folder preference to the new layout preference
		if (!store.isDefault(IPreferenceIds.SYNCVIEW_COMPRESS_FOLDERS) && !store.getBoolean(IPreferenceIds.SYNCVIEW_COMPRESS_FOLDERS)) {
		    // Set the compress folder preference to the default true) \
		    // so will will ignore it in the future
		    store.setToDefault(IPreferenceIds.SYNCVIEW_COMPRESS_FOLDERS);
		    // Set the layout to tree (which was used when compress folder was false)
		    store.setDefault(IPreferenceIds.SYNCVIEW_DEFAULT_LAYOUT, IPreferenceIds.TREE_LAYOUT);
		}
	}

	/**
	 * Convenience method for logging statuses to the plugin log
	 *
	 * @param status  the status to log
	 */
	public static void log(IStatus status) {
		getPlugin().getLog().log(status);
	}

	/**
	 * Convenience method for logging a TeamException in such a way that the
	 * stacktrace is logged as well.
	 * @param e
	 */
	public static void log(CoreException e) {
		IStatus status = e.getStatus();
		log (status.getSeverity(), status.getMessage(), e);
	}

	/**
	 * Log the given exception along with the provided message and severity
	 * indicator
	 *
	 * @param severity
	 *            the severity
	 * @param message
	 *            a human-readable message, localized to the current locale
	 * @param e
	 *            a low-level exception, or <code>null</code> if not applicable
	 */
	public static void log(int severity, String message, Throwable e) {
		log(new Status(severity, ID, 0, message, e));
	}

	/**
	 * @see Plugin#start(BundleContext)
	 */
	@Override
	public void start(BundleContext context) throws Exception {
		super.start(context);

		// register debug options listener
		Hashtable<String, String> properties = new Hashtable<>(2);
		properties.put(DebugOptions.LISTENER_SYMBOLICNAME, ID);
		debugRegistration = context.registerService(DebugOptionsListener.class, Policy.DEBUG_OPTIONS_LISTENER, properties);

		initializeImages(this);

		// This is a backwards compatibility check to ensure that repository
		// provider capability are enabled automatically if an old workspace is
		// opened for the first time and contains projects shared with a disabled
		// capability. We defer the actual processing of the projects to another
		// job since it is not critical to the startup of the team ui plugin.
		IPreferenceStore store = getPreferenceStore();
		if (store.getBoolean(IPreferenceIds.PREF_WORKSPACE_FIRST_TIME)) {
			Job capabilityInitializer = new Job(TeamUIMessages.LoadingTeamCapabilities) {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					TeamCapabilityHelper.getInstance();
					getPreferenceStore().setValue(IPreferenceIds.PREF_WORKSPACE_FIRST_TIME, false);
					return Status.OK_STATUS;
				}
				@Override
				public boolean shouldRun() {
				    // Only initialize the capability helper if the UI is running (bug 76348)
				    return PlatformUI.isWorkbenchRunning();
				}
			};
			capabilityInitializer.setSystem(true);
			capabilityInitializer.setPriority(Job.DECORATE);
			capabilityInitializer.schedule(1000);
		}

		StreamMergerDelegate.start();
	}

	/* (non-Javadoc)
	 * @see Plugin#stop(BundleContext)
	 */
	@Override
	public void stop(BundleContext context) throws Exception {
		try {
			// unregister debug options listener
			debugRegistration.unregister();
			debugRegistration = null;

			if (synchronizeManager != null)
				synchronizeManager.dispose();
		} finally {
			super.stop(context);
		}
		if (provider != null) {
			provider.dispose();
		}
		for (Iterator<TeamStateProvider> iter = decoratedStateProviders.values().iterator(); iter.hasNext();) {
			SubscriberTeamStateProvider sdsp = (SubscriberTeamStateProvider) iter.next();
			sdsp.dispose();
		}
	}

	/**
	 * Register for changes made to Team properties.
	 * @param listener the listener to register
	 */
	public static void addPropertyChangeListener(IPropertyChangeListener listener) {
		propertyChangeListeners.add(listener);
	}

	/**
	 * Deregister as a Team property changes.
	 * @param listener the listener to remove
	 */
	public static void removePropertyChangeListener(IPropertyChangeListener listener) {
		propertyChangeListeners.remove(listener);
	}

	/**
	 * Broadcast a Team property change.
	 * @param event the property change event object
	 */
	public static void broadcastPropertyChange(PropertyChangeEvent event) {
		for (Iterator<IPropertyChangeListener> it = propertyChangeListeners.iterator(); it.hasNext();) {
			IPropertyChangeListener listener = it.next();
			listener.propertyChange(event);
		}
	}

	/**
	 * Creates an image and places it in the image registry.
	 *
	 * @param id  the identifier for the image
	 * @param baseURL  the base URL for the image
	 */
	private static void createImageDescriptor(TeamUIPlugin plugin, String id) {
		// Delegate to the plugin instance to avoid concurrent class loading problems
		plugin.privateCreateImageDescriptor(id);
	}
	private void privateCreateImageDescriptor(String id) {
        ImageDescriptor desc = ImageDescriptor.createFromURL(getImageUrl(id));
        imageDescriptors.put(id, desc);
	}
	private void privateCreateImageDescriptor(String id, String imageUrl) {
        ImageDescriptor desc = ImageDescriptor.createFromURL(getImageUrl(imageUrl));
        imageDescriptors.put(id, desc);
	}

	/**
	 * Returns the image descriptor for the given image ID.
	 * Returns null if there is no such image.
	 *
	 * @param id  the identifier for the image to retrieve
	 * @return the image associated with the given ID
	 */
	public static ImageDescriptor getImageDescriptor(String id) {
		// Delegate to the plugin instance to avoid concurrent class loading problems
		return getPlugin().privateGetImageDescriptor(id);
	}
	private ImageDescriptor privateGetImageDescriptor(String id) {
		if(! imageDescriptors.containsKey(id)) {
			createImageDescriptor(getPlugin(), id);
		}
		return imageDescriptors.get(id);
	}

	/**
	 * Convenience method to get an image descriptor for an extension
	 *
	 * @param extension  the extension declaring the image
	 * @param subdirectoryAndFilename  the path to the image
	 * @return the image
	 */
	public static ImageDescriptor getImageDescriptorFromExtension(IExtension extension, String subdirectoryAndFilename) {
		URL fullPathString = FileLocator.find(Platform.getBundle(extension.getNamespaceIdentifier()), new Path(subdirectoryAndFilename), null);
		return ImageDescriptor.createFromURL(fullPathString);
	}

	public static final String FILE_DIRTY_OVR = "ovr/dirty_ov.png"; //$NON-NLS-1$
	public static final String FILE_CHECKEDIN_OVR = "ovr/version_controlled.png"; //$NON-NLS-1$
	public static final String FILE_CHECKEDOUT_OVR = "ovr/checkedout_ov.png"; //$NON-NLS-1$
	public static final String FILE_CONFLICT_OVR = "ovr/confchg_ov.png"; //$NON-NLS-1$
	public static final String FILE_ERROR_OVR = "ovr/error_co.png"; //$NON-NLS-1$
	public static final String FILE_WARNING_OVR = "ovr/warning_co.png"; //$NON-NLS-1$
	public static final String FILE_HOURGLASS_OVR = "ovr/waiting_ovr.png"; //$NON-NLS-1$
	/*
	 * Initializes the table of images used in this plugin. The plugin is
	 * provided because this method is called before the plugin staic
	 * variable has been set. See the comment on the getPlugin() method
	 * for a description of why this is required.
	 */
	private void initializeImages(TeamUIPlugin plugin) {
		// Overlays

		privateCreateImageDescriptor(ISharedImages.IMG_DIRTY_OVR, FILE_DIRTY_OVR);
		privateCreateImageDescriptor(ISharedImages.IMG_CONFLICT_OVR, FILE_CONFLICT_OVR);
		privateCreateImageDescriptor(ISharedImages.IMG_CHECKEDIN_OVR, FILE_CHECKEDIN_OVR);
		privateCreateImageDescriptor(ISharedImages.IMG_CHECKEDOUT_OVR, FILE_CHECKEDOUT_OVR);
		privateCreateImageDescriptor(ISharedImages.IMG_ERROR_OVR, FILE_ERROR_OVR);
		privateCreateImageDescriptor(ISharedImages.IMG_WARNING_OVR, FILE_WARNING_OVR);
		privateCreateImageDescriptor(ISharedImages.IMG_HOURGLASS_OVR, FILE_HOURGLASS_OVR);

		// Target Management Icons
		createImageDescriptor(plugin, ITeamUIImages.IMG_SITE_ELEMENT);

		// Sync View Icons
		createImageDescriptor(plugin, ITeamUIImages.IMG_DLG_SYNC_INCOMING);
		createImageDescriptor(plugin, ITeamUIImages.IMG_DLG_SYNC_OUTGOING);
		createImageDescriptor(plugin, ITeamUIImages.IMG_DLG_SYNC_CONFLICTING);
		createImageDescriptor(plugin, ITeamUIImages.IMG_REFRESH);
		createImageDescriptor(plugin, ITeamUIImages.IMG_CHANGE_FILTER);
		createImageDescriptor(plugin, ITeamUIImages.IMG_IGNORE_WHITESPACE);
		createImageDescriptor(plugin, ITeamUIImages.IMG_COLLAPSE_ALL);
		createImageDescriptor(plugin, ITeamUIImages.IMG_COLLAPSE_ALL_ENABLED);

		createImageDescriptor(plugin, ITeamUIImages.IMG_DLG_SYNC_INCOMING_DISABLED);
		createImageDescriptor(plugin, ITeamUIImages.IMG_DLG_SYNC_OUTGOING_DISABLED);
		createImageDescriptor(plugin, ITeamUIImages.IMG_DLG_SYNC_CONFLICTING_DISABLED);
		createImageDescriptor(plugin, ITeamUIImages.IMG_REFRESH_DISABLED);
		createImageDescriptor(plugin, ITeamUIImages.IMG_IGNORE_WHITESPACE_DISABLED);

		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_CATCHUP);
		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_RELEASE);
		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_FREE);

		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_CATCHUP_DISABLED);
		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_RELEASE_DISABLED);
		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_FREE_DISABLED);

		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_CATCHUP_ENABLED);
		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_RELEASE_ENABLED);
		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_MODE_FREE_ENABLED);

		// Wizard banners
		createImageDescriptor(plugin, ITeamUIImages.IMG_PROJECTSET_IMPORT_BANNER);
		createImageDescriptor(plugin, ITeamUIImages.IMG_PROJECTSET_EXPORT_BANNER);
		createImageDescriptor(plugin, ITeamUIImages.IMG_WIZBAN_SHARE);

		// Live Sync View icons
		createImageDescriptor(plugin, ITeamUIImages.IMG_COMPRESSED_FOLDER);
		createImageDescriptor(plugin, ITeamUIImages.IMG_SYNC_VIEW);
		createImageDescriptor(plugin, ITeamUIImages.IMG_HIERARCHICAL);

		// Local History Page
		createImageDescriptor(plugin, ITeamUIImages.IMG_DATES_CATEGORY);
		createImageDescriptor(plugin, ITeamUIImages.IMG_COMPARE_VIEW);
		createImageDescriptor(plugin, ITeamUIImages.IMG_LOCALREVISION_TABLE);
	}

    private URL getImageUrl(String relative) {
        return FileLocator.find(Platform.getBundle(PLUGIN_ID), new Path(ICON_PATH + relative), null);
    }

	/**
	 * Returns the standard display to be used. The method first checks, if the
	 * thread calling this method has an associated display. If so, this display
	 * is returned. Otherwise the method returns the display for this workbench.
	 *
	 * @return the standard display to be used
	 */
	public static Display getStandardDisplay() {
		Display display = Display.getCurrent();
		if (display == null) {
			display = PlatformUI.getWorkbench().getDisplay();
		}
		return display;
	}

	public Image getImage(String key) {
		Image image = getImageRegistry().get(key);
		if(image == null) {
			ImageDescriptor d = getImageDescriptor(key);
			image = d.createImage();
			getImageRegistry().put(key, image);
		}
		return image;
	}

	public static void run(IRunnableWithProgress runnable) {
		try {
			PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(true, true, runnable);
		} catch (InvocationTargetException e) {
			Utils.handleError(getStandardDisplay().getActiveShell(), e, null, null);
		} catch (InterruptedException e2) {
			// Nothing to be done
		}
	}

	public org.osgi.service.prefs.Preferences getInstancePreferences() {
		return InstanceScope.INSTANCE.getNode(getBundle().getSymbolicName());
	}

	public synchronized TeamStateProvider getDecoratedStateProvider(RepositoryProviderType rpt) {
		TeamStateProvider provider = decoratedStateProviders.get(rpt.getID());
		if (provider != null)
			return provider;
		Subscriber subscriber = rpt.getSubscriber();
		if (subscriber != null) {
			provider = new SubscriberTeamStateProvider(subscriber);
			decoratedStateProviders.put(rpt.getID(), provider);
			return provider;
		}
		return null;
	}

	/**
	 * Return a decorated state provider that delegates to the appropriate team
	 * provider.
	 * @return a decorated state provider that delegates to the appropriate team
	 * provider
	 */
	public synchronized ITeamStateProvider getDecoratedStateProvider() {
		if (provider == null)
			provider = new WorkspaceTeamStateProvider();
		return provider;
	}

	public ISynchronizeManager getSynchronizeManager() {
		if (synchronizeManager == null) {
			synchronizeManager = new SynchronizeManager();
		}
		return synchronizeManager;
	}
}
