/*******************************************************************************
 * Copyright (c) 2007, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui.internal.services;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.ui.AbstractSourceProvider;
import org.eclipse.ui.ISources;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.services.AbstractServiceFactory;
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.ui.statushandlers.StatusManager;

/**
 * This class will create a service from the matching factory. If the factory
 * doesn't exist, it will try and load it from the registry.
 *
 * @since 3.4
 */
public class WorkbenchServiceRegistry implements IExtensionChangeHandler {
	/**
	 *
	 */
	private static final String WORKBENCH_LEVEL = "workbench"; //$NON-NLS-1$

	private static final String EXT_ID_SERVICES = "org.eclipse.ui.services"; //$NON-NLS-1$

	private static WorkbenchServiceRegistry registry = null;

	public static WorkbenchServiceRegistry getRegistry() {
		if (registry == null) {
			registry = new WorkbenchServiceRegistry();
		}
		return registry;
	}

	private WorkbenchServiceRegistry() {
		PlatformUI.getWorkbench().getExtensionTracker().registerHandler(this,
				ExtensionTracker.createExtensionPointFilter(getExtensionPoint()));
	}

	/**
	 * Used as the global service locator's parent.
	 */
	public static final IServiceLocator GLOBAL_PARENT = new IServiceLocator() {
		@Override
		public <T> T getService(Class<T> api) {
			return null;
		}

		@Override
		public boolean hasService(Class<?> api) {
			return false;
		}
	};

	private Map factories = new HashMap();

	static class ServiceFactoryHandle {
		AbstractServiceFactory factory;
		WeakHashMap serviceLocators = new WeakHashMap();
		String[] serviceNames;

		ServiceFactoryHandle(AbstractServiceFactory factory) {
			this.factory = factory;
		}
	}

	public Object getService(Class key, IServiceLocator parentLocator, ServiceLocator locator) {
		ServiceFactoryHandle handle = (ServiceFactoryHandle) factories.get(key.getName());
		if (handle == null) {
			handle = loadFromRegistry(key);
		}
		if (handle != null) {
			Object result = handle.factory.create(key, parentLocator, locator);
			if (result != null) {
				handle.serviceLocators.put(locator, new Object());
				return result;
			}
		}
		return null;
	}

	private ServiceFactoryHandle loadFromRegistry(Class key) {
		ServiceFactoryHandle result = null;
		IConfigurationElement[] serviceFactories = getExtensionPoint().getConfigurationElements();
		try {
			final String requestedName = key.getName();
			boolean done = false;
			for (int i = 0; i < serviceFactories.length && !done; i++) {
				final IConfigurationElement[] serviceNameElements = serviceFactories[i]
						.getChildren(IWorkbenchRegistryConstants.TAG_SERVICE);
				for (int j = 0; j < serviceNameElements.length && !done; j++) {
					String serviceName = serviceNameElements[j]
							.getAttribute(IWorkbenchRegistryConstants.ATTR_SERVICE_CLASS);
					if (requestedName.equals(serviceName)) {
						done = true;
					}
				}
				if (done) {
					final AbstractServiceFactory f = (AbstractServiceFactory) serviceFactories[i]
							.createExecutableExtension(IWorkbenchRegistryConstants.ATTR_FACTORY_CLASS);
					ServiceFactoryHandle handle = new ServiceFactoryHandle(f);
					PlatformUI.getWorkbench().getExtensionTracker().registerObject(
							serviceFactories[i].getDeclaringExtension(), handle, IExtensionTracker.REF_WEAK);

					List serviceNames = new ArrayList();
					for (IConfigurationElement configElement : serviceNameElements) {
						String serviceName = configElement.getAttribute(IWorkbenchRegistryConstants.ATTR_SERVICE_CLASS);
						if (factories.containsKey(serviceName)) {
							WorkbenchPlugin.log("Factory already exists for " //$NON-NLS-1$
									+ serviceName);
						} else {
							factories.put(serviceName, handle);
							serviceNames.add(serviceName);
						}
					}
					handle.serviceNames = (String[]) serviceNames.toArray(new String[serviceNames.size()]);
					result = handle;
				}
			}
		} catch (CoreException e) {
			StatusManager.getManager().handle(e.getStatus());
		}
		return result;
	}

	private IExtensionPoint getExtensionPoint() {
		IExtensionRegistry reg = Platform.getExtensionRegistry();
		return reg.getExtensionPoint(EXT_ID_SERVICES);
	}

	public AbstractSourceProvider[] getSourceProviders() {
		ArrayList providers = new ArrayList();
		IExtensionPoint ep = getExtensionPoint();
		for (IConfigurationElement configElement : ep.getConfigurationElements()) {
			if (configElement.getName().equals(IWorkbenchRegistryConstants.TAG_SOURCE_PROVIDER)) {
				try {
					Object sourceProvider = configElement
							.createExecutableExtension(IWorkbenchRegistryConstants.ATTR_PROVIDER);
					if (!(sourceProvider instanceof AbstractSourceProvider)) {
						String attributeName = configElement.getAttribute(IWorkbenchRegistryConstants.ATTR_PROVIDER);
						final String message = "Source Provider '" + //$NON-NLS-1$
								attributeName + "' should extend AbstractSourceProvider"; //$NON-NLS-1$
						final IStatus status = new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH, message);
						WorkbenchPlugin.log(status);
						continue;
					}
					providers.add(sourceProvider);
					processVariables(configElement.getChildren(IWorkbenchRegistryConstants.TAG_VARIABLE));
				} catch (CoreException e) {
					StatusManager.getManager().handle(e.getStatus());
				}
			}
		}
		return (AbstractSourceProvider[]) providers.toArray(new AbstractSourceProvider[providers.size()]);
	}

	private static final String[] supportedLevels = { ISources.ACTIVE_CONTEXT_NAME, ISources.ACTIVE_SHELL_NAME,
			ISources.ACTIVE_WORKBENCH_WINDOW_NAME, ISources.ACTIVE_EDITOR_ID_NAME, ISources.ACTIVE_PART_ID_NAME,
			ISources.ACTIVE_SITE_NAME };

	private void processVariables(IConfigurationElement[] children) {
		for (IConfigurationElement configElement : children) {
			String name = configElement.getAttribute(IWorkbenchRegistryConstants.ATT_NAME);
			if (name == null || name.isEmpty()) {
				continue;
			}
			String level = configElement.getAttribute(IWorkbenchRegistryConstants.ATT_PRIORITY_LEVEL);
			if (level == null || level.isEmpty()) {
				level = WORKBENCH_LEVEL;
			} else {
				boolean found = false;
				for (int j = 0; j < supportedLevels.length && !found; j++) {
					if (supportedLevels[j].equals(level)) {
						found = true;
					}
				}
				if (!found) {
					level = WORKBENCH_LEVEL;
				}
			}
			int existingPriority = SourcePriorityNameMapping.getMapping(level);
			int newPriority = existingPriority << 1;
			SourcePriorityNameMapping.addMapping(name, newPriority);
		}
	}

	@Override
	public void addExtension(IExtensionTracker tracker, IExtension extension) {
		// we don't need to react to adds because we are not caching the extensions we
		// find -
		// next time a service is requested, we will look at all extensions again in
		// loadFromRegistry
	}

	@Override
	public void removeExtension(IExtension extension, Object[] objects) {
		for (Object object : objects) {
			if (object instanceof ServiceFactoryHandle) {
				ServiceFactoryHandle handle = (ServiceFactoryHandle) object;
				Set locatorSet = handle.serviceLocators.keySet();
				ServiceLocator[] locators = (ServiceLocator[]) locatorSet
						.toArray(new ServiceLocator[locatorSet.size()]);
				Arrays.sort(locators, (loc1, loc2) -> {
					int l1 = loc1.getService(IWorkbenchLocationService.class).getServiceLevel();
					int l2 = loc2.getService(IWorkbenchLocationService.class).getServiceLevel();
					return l1 < l2 ? -1 : (l1 > l2 ? 1 : 0);
				});
				for (ServiceLocator locator : locators) {
					ServiceLocator serviceLocator = locator;
					if (!serviceLocator.isDisposed()) {
						serviceLocator.unregisterServices(handle.serviceNames);
					}
				}
				handle.factory = null;
				for (String serviceName : handle.serviceNames) {
					if (factories.get(serviceName) == handle) {
						factories.remove(serviceName);
					}
				}
			}
		}
	}
}
