/*******************************************************************************
 * Copyright (c) 2003, 2007 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;
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 = '=';  

	/*
	 * Set of ids of activated extensions.
	 */
	//private final Set activatedExtensions = new HashSet();

	/*
	 * Set of ids of activated extensions.
	 */
	private final Map/*<String, Boolean>*/ activatedExtensionsMap = new HashMap();

	/*
	 * 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.
	 */
	public boolean isNavigatorExtensionActive(String aNavigatorExtensionId) {
		Boolean b = (Boolean) activatedExtensionsMap.get(aNavigatorExtensionId);
		if(b != null)
			return b.booleanValue();
		synchronized (activatedExtensionsMap) {
			NavigatorContentDescriptor descriptor = CONTENT_DESCRIPTOR_REGISTRY.getContentDescriptor(aNavigatorExtensionId);
			if(descriptor.isActiveByDefault())
				activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.TRUE);
			else
				activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.FALSE);
			return descriptor.isActiveByDefault();
		}
		//return activatedExtensions.contains(aNavigatorExtensionId);
	}

	/**
	 * 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) {
			//activatedExtensions.add(aNavigatorExtensionId);
			activatedExtensionsMap.put(aNavigatorExtensionId, Boolean.TRUE);
		} else {
			//activatedExtensions.remove(aNavigatorExtensionId);
			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 (int i = 0; i < aNavigatorExtensionIds.length; i++) {
				//activatedExtensions.add(aNavigatorExtensionIds[i]);
				activatedExtensionsMap.put(aNavigatorExtensionIds[i], Boolean.TRUE);
			}
		} else {
			for (int i = 0; i < aNavigatorExtensionIds.length; i++) {
				//activatedExtensions.remove(aNavigatorExtensionIds[i]);
				activatedExtensionsMap.put(aNavigatorExtensionIds[i], Boolean.FALSE);
			}
		}
		notifyListeners(aNavigatorExtensionIds, toEnable);

	}

	/**
	 * Save the activation state for the given viewer.
	 * 
	 */
	public void persistExtensionActivations() {

		Preferences preferences = NavigatorPlugin.getDefault()
				.getPluginPreferences();

		//synchronized (activatedExtensions) {
		synchronized (activatedExtensionsMap) {
			//Iterator activatedExtensionsIterator = activatedExtensions.iterator();
			Iterator 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 = (String) activatedExtensionsIterator.next();
				isActive = isNavigatorExtensionActive(navigatorExtensionId);
				preferenceValue.append(navigatorExtensionId)
									.append(EQUALS)
										.append( isActive ? Boolean.TRUE : Boolean.FALSE )				
											.append(DELIM);
			}
			preferences.setValue(getPreferenceKey(), preferenceValue.toString());
		}
		NavigatorPlugin.getDefault().savePluginPreferences();
	}

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

	/**
	 * No longer receive notification when activation state changes.
	 * 
	 * @param aListener
	 *            An implementation of {@link IExtensionActivationListener}
	 */
	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 (int i = 0; i < listenerArray.length; i++) {
				((IExtensionActivationListener) listenerArray[i])
						.onExtensionActivation(contentService.getViewerId(),
								navigatorExtensionIds, toEnable);
			}
		}

	}

	private void revertExtensionActivations() {

		Preferences preferences = NavigatorPlugin.getDefault()
				.getPluginPreferences();

		String activatedExtensionsString = preferences
				.getString(getPreferenceKey());

		if (activatedExtensionsString != null
				&& activatedExtensionsString.length() > 0) {
			String[] contentExtensionIds = activatedExtensionsString
					.split(DELIM);
			
			String id = null;
			String booleanString = null;
			int indx=0;
			for (int i = 0; i < contentExtensionIds.length; i++) {
				//activatedExtensions.add(contentExtensionIds[i]);
				if( (indx = contentExtensionIds[i].indexOf(EQUALS)) > -1) {
					// up to but not including the equals
					id = contentExtensionIds[i].substring(0, indx);
					booleanString = contentExtensionIds[i].substring(indx+1, contentExtensionIds[i].length());
					activatedExtensionsMap.put(id, Boolean.valueOf(booleanString));
				} else {
					// IS THIS THE RIGHT WAY TO HANDLE THIS CASE?
					NavigatorContentDescriptor descriptor = CONTENT_DESCRIPTOR_REGISTRY.getContentDescriptor(contentExtensionIds[i]);
					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 (int i = 0; i < contentDescriptors.length; i++) {
				if (contentDescriptors[i].isActiveByDefault()) {					
					//activatedExtensions.add(contentDescriptors[i].getId());
					activatedExtensionsMap.put(contentDescriptors[i].getId(), Boolean.TRUE);
				}
			}
		} 
	}

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


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

		Set activatedDescriptors = new HashSet(); 
		setActive(extensionIds, true);
		for (int extId = 0; extId < extensionIds.length; extId++) {
			activatedDescriptors.add(CONTENT_DESCRIPTOR_REGISTRY
					.getContentDescriptor(extensionIds[extId]));
		}

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

			for (int descriptorIndx = 0; descriptorIndx < descriptors.length; descriptorIndx++) {
				for (int extId = 0; extId < extensionIds.length; extId++) {
					if (descriptors[descriptorIndx].getId().equals(
							extensionIds[extId])) {
						descriptorList.remove(descriptors[descriptorIndx]);
					}
				}
			}

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

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

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

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

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

			for (int descriptorIndx = 0; descriptorIndx < descriptors.length; descriptorIndx++) {
				for (int extId = 0; extId < extensionIds.length; extId++) {
					if (descriptors[descriptorIndx].getId().equals(
							extensionIds[extId])) {
						descriptorList.remove(descriptors[descriptorIndx]);
					}
				}
			}

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

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


}
