/*******************************************************************************
 *  Copyright (c) 2004, 2016 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
 *     Mickael Istria (Red Hat Inc.) - Bug 485227
 *******************************************************************************/
package org.eclipse.core.internal.content;

import java.io.InputStream;
import java.io.Reader;
import java.util.*;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.*;
import org.eclipse.core.runtime.preferences.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.service.prefs.BackingStoreException;

public class ContentTypeManager extends ContentTypeMatcher implements IContentTypeManager {
	private static class ContentTypeRegistryChangeListener implements IRegistryChangeListener {
		@Override
		public void registryChanged(IRegistryChangeEvent event) {
			// no changes related to the content type registry
			if (event.getExtensionDeltas(IContentConstants.RUNTIME_NAME, ContentTypeBuilder.PT_CONTENTTYPES).length == 0
					&& event.getExtensionDeltas(IContentConstants.CONTENT_NAME,
							ContentTypeBuilder.PT_CONTENTTYPES).length == 0)
				return;
			getInstance().invalidate();
		}
	}

	private static IRegistryChangeListener runtimeExtensionListener = new ContentTypeRegistryChangeListener();
	private static IRegistryChangeListener contentExtensionListener = new ContentTypeRegistryChangeListener();

	private static ContentTypeManager instance;

	public static final int BLOCK_SIZE = 0x400;
	public static final String CONTENT_TYPE_PREF_NODE = IContentConstants.RUNTIME_NAME + IPath.SEPARATOR + "content-types"; //$NON-NLS-1$
	private static final String OPTION_DEBUG_CONTENT_TYPES = "org.eclipse.core.contenttype/debug"; //$NON-NLS-1$;
	static final boolean DEBUGGING = Activator.getDefault().getBooleanDebugOption(OPTION_DEBUG_CONTENT_TYPES, false);
	private ContentTypeCatalog catalog;
	private int catalogGeneration;

	/**
	 * List of registered listeners (element type:
	 * <code>IContentTypeChangeListener</code>).
	 * These listeners are to be informed when
	 * something in a content type changes.
	 */
	protected final ListenerList<IContentTypeChangeListener> contentTypeListeners = new ListenerList<>();

	/**
	 * Creates and initializes the platform's content type manager. A reference to the
	 * content type manager can later be obtained by calling <code>getInstance()</code>.
	 */
	// TODO we can remove this sometime, it is no longer needed
	public static void startup() {
		getInstance();
	}

	public static void addRegistryChangeListener(IExtensionRegistry registry) {
		if (registry == null)
			return;
		// Different instances of listener required. See documentation of
		// IExtensionRegistry.addRegistryChangeListener(IRegistryChangeListener, String).
		registry.addRegistryChangeListener(runtimeExtensionListener, IContentConstants.RUNTIME_NAME);
		registry.addRegistryChangeListener(contentExtensionListener, IContentConstants.CONTENT_NAME);
	}

	/**
	 * Shuts down the platform's content type manager. After this call returns,
	 * the content type manager will be closed for business.
	 */
	public static void shutdown() {
		// there really is nothing left to do except null the instance.
		instance = null;
	}

	public static void removeRegistryChangeListener(IExtensionRegistry registry) {
		if (registry == null)
			return;
		getInstance().invalidate();
		registry.removeRegistryChangeListener(runtimeExtensionListener);
		registry.removeRegistryChangeListener(contentExtensionListener);
	}

	/**
	 * Obtains this platform's content type manager.
	 *
	 * @return the content type manager
	 */
	public static ContentTypeManager getInstance() {
		if (instance == null)
			instance = new ContentTypeManager();
		return instance;
	}

	/*
	 * Returns the extension for a file name (omitting the leading '.').
	 */
	static String getFileExtension(String fileName) {
		int dotPosition = fileName.lastIndexOf('.');
		return (dotPosition == -1 || dotPosition == fileName.length() - 1) ? "" : fileName.substring(dotPosition + 1); //$NON-NLS-1$
	}

	protected static ILazySource readBuffer(InputStream contents) {
		return new LazyInputStream(contents, BLOCK_SIZE);
	}

	protected static ILazySource readBuffer(Reader contents) {
		return new LazyReader(contents, BLOCK_SIZE);
	}

	public ContentTypeManager() {
		super(null, InstanceScope.INSTANCE);
	}

	protected ContentTypeBuilder createBuilder(ContentTypeCatalog newCatalog) {
		return new ContentTypeBuilder(newCatalog);
	}

	@Override
	public IContentType[] getAllContentTypes() {
		ContentTypeCatalog currentCatalog = getCatalog();
		IContentType[] types = currentCatalog.getAllContentTypes();
		IContentType[] result = new IContentType[types.length];
		int generation = currentCatalog.getGeneration();
		for (int i = 0; i < result.length; i++)
			result[i] = new ContentTypeHandler((ContentType) types[i], generation);
		return result;
	}

	protected synchronized ContentTypeCatalog getCatalog() {
		if (catalog != null)
			// already has one
			return catalog;
		// create new catalog
		ContentTypeCatalog newCatalog = new ContentTypeCatalog(this, catalogGeneration++);
		// build catalog by parsing the extension registry
		ContentTypeBuilder builder = createBuilder(newCatalog);
		try {
			builder.buildCatalog(getContext());
			// only remember catalog if building it was successful
			catalog = newCatalog;
		} catch (InvalidRegistryObjectException e) {
			// the registry has stale objects... just don't remember the returned (incomplete) catalog
		}
		newCatalog.organize();
		return newCatalog;
	}

	@Override
	public IContentType getContentType(String contentTypeIdentifier) {
		ContentTypeCatalog currentCatalog = getCatalog();
		ContentType type = currentCatalog.getContentType(contentTypeIdentifier);
		return type == null ? null : new ContentTypeHandler(type, currentCatalog.getGeneration());
	}

	@Override
	public IContentTypeMatcher getMatcher(final ISelectionPolicy customPolicy, final IScopeContext context) {
		return new ContentTypeMatcher(customPolicy, context == null ? getContext() : context);
	}

	IEclipsePreferences getPreferences() {
		return getPreferences(getContext());
	}

	IEclipsePreferences getPreferences(IScopeContext context) {
		return context.getNode(CONTENT_TYPE_PREF_NODE);
	}

	/**
	 * Causes a new catalog to be built afresh next time an API call is made.
	 */
	synchronized void invalidate() {
		if (ContentTypeManager.DEBUGGING && catalog != null)
			ContentMessages.message("Registry discarded"); //$NON-NLS-1$
		catalog = null;
	}

	@Override
	public void addContentTypeChangeListener(IContentTypeChangeListener listener) {
		contentTypeListeners.add(listener);
	}

	@Override
	public void removeContentTypeChangeListener(IContentTypeChangeListener listener) {
		contentTypeListeners.remove(listener);
	}

	public void fireContentTypeChangeEvent(IContentType type) {
		IContentType eventObject = type;
		if (type instanceof ContentType) {
			eventObject = new ContentTypeHandler((ContentType) type, ((ContentType) type).getCatalog().getGeneration());
		} else {
			eventObject = type;
		}
		for (final IContentTypeChangeListener listener : this.contentTypeListeners) {
			final ContentTypeChangeEvent event = new ContentTypeChangeEvent(eventObject);
			ISafeRunnable job = new ISafeRunnable() {
				@Override
				public void handleException(Throwable exception) {
					// already logged in SafeRunner#run()
				}

				@Override
				public void run() throws Exception {
					listener.contentTypeChanged(event);
				}
			};
			SafeRunner.run(job);
		}
	}

	@Override
	public IContentDescription getSpecificDescription(BasicDescription description) {
		// this is the platform content type manager, no specificities
		return description;
	}

	@Override
	public final void removeContentType(String contentTypeIdentifier) throws CoreException {
		if (contentTypeIdentifier == null) {
			return;
		}
		IContentType contentType = getContentType(contentTypeIdentifier);
		if (contentType == null) {
			return;
		}
		if (!contentType.isUserDefined()) {
			throw new IllegalArgumentException("Can only delete content-types defined by users."); //$NON-NLS-1$
		}
		getCatalog().removeContentType(contentType.getId());
		// Remove preferences for this content type.
		List<String> userDefinedIds = new ArrayList<>(Arrays.asList(getUserDefinedContentTypeIds()));
		userDefinedIds.remove(contentType.getId());
		getContext().getNode(ContentType.PREF_USER_DEFINED).put(ContentType.PREF_USER_DEFINED,
				userDefinedIds.stream().collect(Collectors.joining(ContentType.PREF_USER_DEFINED__SEPARATOR)));
		try {
			getContext().getNode(ContentType.PREF_USER_DEFINED).flush();
		} catch (BackingStoreException e) {
			String message = NLS.bind(ContentMessages.content_errorSavingSettings, contentType.getId());
			IStatus status = new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, e);
			throw new CoreException(status);
		}
		getCatalog().organize();
		fireContentTypeChangeEvent(contentType);
	}

	@Override
	public final IContentType addContentType(String id, String name, IContentType baseType) throws CoreException {
		if (id == null) {
			throw new IllegalArgumentException("Content-type 'id' mustn't be null");//$NON-NLS-1$
		}
		if (id.contains(ContentType.PREF_USER_DEFINED__SEPARATOR)) {
			throw new IllegalArgumentException(
					"Content-Type id mustn't contain '" + ContentType.PREF_USER_DEFINED__SEPARATOR + '\''); //$NON-NLS-1$
		}
		if (getContentType(id) != null) {
			throw new IllegalArgumentException("Content-type '" + id + "' already exists.");//$NON-NLS-1$ //$NON-NLS-2$
		}
		ContentType contentType = ContentType.createContentType(getCatalog(), id, name, (byte) 0, new String[0],
				new String[0], new String[0], baseType != null ? baseType.getId() : null, null, null, null);
		getCatalog().addContentType(contentType);
		// Add preferences for this content type.
		String currentUserDefined = getContext().getNode(ContentType.PREF_USER_DEFINED)
				.get(ContentType.PREF_USER_DEFINED, ContentType.EMPTY_STRING);
		if (currentUserDefined.length() > 0) {
			currentUserDefined += ContentType.PREF_USER_DEFINED__SEPARATOR;
		}
		getContext().getNode(ContentType.PREF_USER_DEFINED).put(ContentType.PREF_USER_DEFINED, currentUserDefined + id);
		contentType.setValidation(ContentType.STATUS_UNKNOWN);
		IEclipsePreferences contextTypeNode = getContext().getNode(contentType.getId());
		contextTypeNode.put(ContentType.PREF_USER_DEFINED__NAME, name);
		if (baseType != null) {
			contextTypeNode.put(ContentType.PREF_USER_DEFINED__BASE_TYPE_ID, baseType.getId());
		}
		try {
			getContext().getNode(ContentType.PREF_USER_DEFINED).flush();
			contextTypeNode.flush();
		} catch (BackingStoreException e) {
			String message = NLS.bind(ContentMessages.content_errorSavingSettings, id);
			IStatus status = new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, e);
			throw new CoreException(status);
		}
		getCatalog().organize();
		fireContentTypeChangeEvent(contentType);
		return contentType;
	}

	private String[] getUserDefinedContentTypeIds() {
		return getUserDefinedContentTypeIds(getContext());
	}

	static String[] getUserDefinedContentTypeIds(IScopeContext context) {
		String ids = context.getNode(ContentType.PREF_USER_DEFINED)
				.get(ContentType.PREF_USER_DEFINED, ContentType.EMPTY_STRING);
		if (ids.isEmpty()) {
			return new String[0];
		}
		return ids.split(ContentType.PREF_USER_DEFINED__SEPARATOR);
	}
}
