/*******************************************************************************
 * 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.getContributor().getName()), 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;
	}
}
