/*******************************************************************************
 * Copyright (c) 2003, 2015 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.ui.internal.navigator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.ui.internal.navigator.extensions.NavigatorContentDescriptor;
import org.eclipse.ui.internal.navigator.extensions.NavigatorContentDescriptorManager;
import org.eclipse.ui.navigator.IExtensionActivationListener;
import org.eclipse.ui.navigator.INavigatorActivationService;
import org.eclipse.ui.navigator.INavigatorContentDescriptor;
import org.eclipse.ui.navigator.INavigatorContentService;

/**
 *
 * The activation service determines if an extension is <i>active</i> within the
 * context of a given viewer. If an extension is <i>active</i> then the extension
 * will contribute functionality to the viewer. If an extension is not <i>active</i>,
 * then the extension will not be given opportunities to contribute
 * functionality to the given viewer. See {@link INavigatorContentService} for
 * more detail on what states are associated with a content extension.
 *
 * @since 3.2
 */
public final class NavigatorActivationService implements
		INavigatorActivationService {

	private static final String ACTIVATED_EXTENSIONS = ".activatedExtensions"; //$NON-NLS-1$

	private static final NavigatorContentDescriptorManager CONTENT_DESCRIPTOR_REGISTRY = NavigatorContentDescriptorManager
			.getInstance();

	private static final INavigatorContentDescriptor[] NO_DESCRIPTORS = new INavigatorContentDescriptor[0];

	private static final String DELIM = ";"; //$NON-NLS-1$

	private static final char EQUALS = '=';

	/*
	 * Map of ids of activated extensions. Note this is only synchronized when
	 * modifying it structurally (that is adding or deleting entries in it). For
	 * changing of the activated extension state, no synchronization is
	 * necessary.  Though this is semantically functioning as a Set, it's implemented
	 * as a Map to avoid the synchronization during the frequent checking of
	 * extension status.
	 */
	private final Map<String, Boolean> activatedExtensionsMap = new HashMap<String, Boolean>();

	/*
	 * IExtensionActivationListeners
	 */
	private final ListenerList listeners = new ListenerList();

	private INavigatorContentService contentService;

	/**
	 * Create an instance of the service.
	 *
	 * @param aContentService
	 *            The associated content service.
	 */
	public NavigatorActivationService(INavigatorContentService aContentService) {
		contentService = aContentService;
		revertExtensionActivations();
	}

	/**
	 *
	 * Checks the known activation state for the given viewer id to determine if
	 * the given navigator extension is 'active'.
	 *
	 * @param aNavigatorExtensionId
	 *            The unique identifier associated with a given extension.
	 *
	 * @return True if the extension is active in the context of the viewer id.
	 */
	@Override
	public boolean isNavigatorExtensionActive(String aNavigatorExtensionId) {
		Boolean b = activatedExtensionsMap.get(aNavigatorExtensionId);
		if(b != null)
			return b.booleanValue();
		synchronized (activatedExtensionsMap) {
			NavigatorContentDescriptor descriptor = CONTENT_DESCRIPTOR_REGISTRY.getContentDescriptor(aNavigatorExtensionId);
			if (descriptor == null)
				return false;
			if(descriptor.isActiveByDefault())
				activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.TRUE);
			else
				activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.FALSE);
			return descriptor.isActiveByDefault();
		}
	}

	/**
	 * Set the activation state for the given extension in the context of the
	 * given viewer id. Each instance of an INavigatorContentService listens for
	 * the activation service to update; and if those instances were created
	 * with viewers, they will issue a refresh. Otherwise, clients are
	 * responsible for refreshing the viewers.
	 *
	 * <p>
	 * Clients must call {@link #persistExtensionActivations()} to save
	 * the the activation state.
	 * </p>
	 *
	 * <p>
	 * When clients are updating a batch of extensions, consider using
	 * {@link #setActive(String[], boolean)} when
	 * possible to avoid unnecessary notifications.
	 * </p>
	 *
	 * @param aNavigatorExtensionId
	 *            The unique identifier associated with a given extension.
	 * @param toEnable
	 *            True indicates the extension should be enabled; False
	 *            indicates otherwise.
	 *
	 */
	public void setActive(
			String aNavigatorExtensionId, boolean toEnable) {

		boolean currentlyActive = isNavigatorExtensionActive(aNavigatorExtensionId);
		if (currentlyActive == toEnable) {
			return;
		}

		if (toEnable) {
			activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.TRUE);
		} else {
			activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.FALSE);
		}
		notifyListeners(new String[] { aNavigatorExtensionId }, toEnable);

	}

	/**
	 * Set the activation state for the given extension in the context of the
	 * given viewer id. Each instance of an INavigatorContentService listens for
	 * the activation service to update; and if those instances were created
	 * with viewers, they will issue a refresh. Otherwise, clients are
	 * responsible for refreshing the viewers.
	 *
	 * <p>
	 * Clients must call {@link #persistExtensionActivations()} to save
	 * the the activation state.
	 * </p>
	 *
	 * @param aNavigatorExtensionIds
	 *            An array of unique identifiers associated with existing
	 *            extension.
	 * @param toEnable
	 *            True indicates the extension should be enabled; False
	 *            indicates otherwise.
	 *
	 */
	public void setActive(String[] aNavigatorExtensionIds,
			boolean toEnable) {

		if (toEnable) {
			for (String aNavigatorExtensionId : aNavigatorExtensionIds) {
				activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.TRUE);
			}
		} else {
			for (String aNavigatorExtensionId : aNavigatorExtensionIds) {
				activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.FALSE);
			}
		}
		notifyListeners(aNavigatorExtensionIds, toEnable);

	}

	/**
	 * Save the activation state for the given viewer.
	 *
	 */
	@Override
	public void persistExtensionActivations() {
		IEclipsePreferences prefs = NavigatorContentService.getPreferencesRoot();

		synchronized (activatedExtensionsMap) {
			Iterator<String> activatedExtensionsIterator = activatedExtensionsMap.keySet().iterator();

			/* ensure that the preference will be non-empty */
			StringBuffer preferenceValue = new StringBuffer();
			String navigatorExtensionId = null;
			boolean isActive = false;
			while (activatedExtensionsIterator.hasNext()) {
				navigatorExtensionId = activatedExtensionsIterator.next();
				isActive = isNavigatorExtensionActive(navigatorExtensionId);
				preferenceValue.append(navigatorExtensionId)
									.append(EQUALS)
										.append( isActive ? Boolean.TRUE : Boolean.FALSE )
											.append(DELIM);
			}
			prefs.put(getPreferenceKey(), preferenceValue.toString());
		}

		NavigatorContentService.flushPreferences(prefs);
	}

	/**
	 * Request notification when the activation state changes for the given
	 * viewer id.
	 *
	 * @param aListener
	 *            An implementation of {@link IExtensionActivationListener}
	 */
	@Override
	public void addExtensionActivationListener(
			IExtensionActivationListener aListener) {
		listeners.add(aListener);
	}

	/**
	 * No longer receive notification when activation state changes.
	 *
	 * @param aListener
	 *            An implementation of {@link IExtensionActivationListener}
	 */
	@Override
	public void removeExtensionActivationListener(
			IExtensionActivationListener aListener) {
		listeners.remove(aListener);
	}

	private void notifyListeners(String[] navigatorExtensionIds,
			boolean toEnable) {

		if(navigatorExtensionIds != null) { // should really never be null, but just in case
			if(navigatorExtensionIds.length > 1)
				Arrays.sort(navigatorExtensionIds);

			Object[] listenerArray = listeners.getListeners();
			for (Object element : listenerArray) {
				((IExtensionActivationListener) element)
						.onExtensionActivation(contentService.getViewerId(),
								navigatorExtensionIds, toEnable);
			}
		}

	}

	private void revertExtensionActivations() {

		IEclipsePreferences prefs = NavigatorContentService.getPreferencesRoot();

		String activatedExtensionsString = prefs
				.get(getPreferenceKey(), null);

		if (activatedExtensionsString != null
				&& activatedExtensionsString.length() > 0) {
			String[] contentExtensionIds = activatedExtensionsString
					.split(DELIM);

			String id = null;
			String booleanString = null;
			int indx=0;
			for (String contentExtensionId : contentExtensionIds) {
				if( (indx = contentExtensionId.indexOf(EQUALS)) > -1) {
					// up to but not including the equals
					id = contentExtensionId.substring(0, indx);
					booleanString = contentExtensionId.substring(indx+1, contentExtensionId.length());
					activatedExtensionsMap.put(id, Boolean.valueOf(booleanString));
				} else {
					// IS THIS THE RIGHT WAY TO HANDLE THIS CASE?
					NavigatorContentDescriptor descriptor = CONTENT_DESCRIPTOR_REGISTRY.getContentDescriptor(contentExtensionId);
					if(descriptor != null)
						activatedExtensionsMap.put(id, Boolean.valueOf(descriptor.isActiveByDefault()));
				}
			}

		} else {
			/*
			 * We add the default activation of every known extension, even
			 * though some may not be bound to the associated content service;
			 * this is because they could be bound at a later time through the
			 * programmatic binding mechanism in INavigatorContentService.
			 */
			INavigatorContentDescriptor[] contentDescriptors = CONTENT_DESCRIPTOR_REGISTRY
					.getAllContentDescriptors();
			for (INavigatorContentDescriptor contentDescriptor : contentDescriptors) {
				if (contentDescriptor.isActiveByDefault()) {
					activatedExtensionsMap.put(contentDescriptor.getId(), Boolean.TRUE);
				}
			}
		}
	}

	private String getPreferenceKey() {
		return contentService.getViewerId() + ACTIVATED_EXTENSIONS;
	}


	@Override
	public INavigatorContentDescriptor[] activateExtensions(
			String[] extensionIds, boolean toDeactivateAllOthers) {

		Set<NavigatorContentDescriptor> activatedDescriptors = new HashSet<NavigatorContentDescriptor>();
		setActive(extensionIds, true);
		for (String extensionId : extensionIds) {
			activatedDescriptors.add(CONTENT_DESCRIPTOR_REGISTRY
					.getContentDescriptor(extensionId));
		}

		if (toDeactivateAllOthers) {
			NavigatorContentDescriptor[] descriptors = CONTENT_DESCRIPTOR_REGISTRY
					.getAllContentDescriptors();
			List<NavigatorContentDescriptor> descriptorList = new ArrayList<NavigatorContentDescriptor>(Arrays.asList(descriptors));

			for (NavigatorContentDescriptor descriptor : descriptors) {
				for (String extensionId : extensionIds) {
					if (descriptor.getId().equals(extensionId)) {
						descriptorList.remove(descriptor);
					}
				}
			}

			String[] deactivatedExtensions = new String[descriptorList.size()];
			for (int i = 0; i < descriptorList.size(); i++) {
				INavigatorContentDescriptor descriptor = descriptorList
						.get(i);
				deactivatedExtensions[i] = descriptor.getId();
			}
			setActive(deactivatedExtensions, false);
		}

		if (activatedDescriptors.size() == 0) {
			return NO_DESCRIPTORS;
		}
		return activatedDescriptors
				.toArray(new NavigatorContentDescriptor[activatedDescriptors
						.size()]);
	}

	@Override
	public INavigatorContentDescriptor[] deactivateExtensions(
			String[] extensionIds, boolean toEnableAllOthers) {

		Set<NavigatorContentDescriptor> activatedDescriptors = new HashSet<NavigatorContentDescriptor>();
		setActive(extensionIds, false);

		if (toEnableAllOthers) {
			NavigatorContentDescriptor[] descriptors = CONTENT_DESCRIPTOR_REGISTRY
					.getAllContentDescriptors();
			List<NavigatorContentDescriptor> descriptorList = new ArrayList<NavigatorContentDescriptor>(Arrays.asList(descriptors));

			for (NavigatorContentDescriptor descriptor : descriptors) {
				for (String extensionId : extensionIds) {
					if (descriptor.getId().equals(extensionId)) {
						descriptorList.remove(descriptor);
					}
				}
			}

			String[] activatedExtensions = new String[descriptorList.size()];
			for (int i = 0; i < descriptorList.size(); i++) {
				NavigatorContentDescriptor descriptor = descriptorList
						.get(i);
				activatedExtensions[i] = descriptor.getId();
				activatedDescriptors.add(descriptor);
			}
			setActive(activatedExtensions,	true);
		}
		if (activatedDescriptors.size() == 0) {
			return NO_DESCRIPTORS;
		}

		return activatedDescriptors
				.toArray(new NavigatorContentDescriptor[activatedDescriptors
						.size()]);
	}


}
