//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.ui.actions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.epf.library.ILibraryServiceListener;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.LibraryServiceUtil;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.prefs.LibraryPreferenceConstants;
import org.eclipse.epf.library.ui.LibraryUIResources;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

/**
 * Adds the Configuration comboxbox to the system toolbar.
 * 
 * @author Bingxue Xu
 * @author Kelvin Low
 * @author Jinhua Xi
 * @since 1.0
 */
public class ConfigurationContributionItem extends ContributionItem {

	private static Combo configCombo;
	private static ComboViewer configComboViewer;
	protected ToolItem item;
	protected CoolItem coolItem;
	private ILibraryServiceListener libSvcListener;

	
	// the "Select a configuration" string
	private static final String SELECT_CONFIGURATION = LibraryUIResources.selectConfigLabel_text;

	protected static IStructuredContentProvider contentProviderConfigs = new AdapterFactoryContentProvider(
			TngAdapterFactory.INSTANCE
			.getNavigatorView_ComposedAdapterFactory()) {
		public Object[] getElements(Object object) {
			List configsList = new ArrayList();
			if (LibraryService.getInstance().getCurrentMethodConfiguration() == null) {
				configsList.add(SELECT_CONFIGURATION);
			}
			configsList.addAll(Arrays.asList(LibraryServiceUtil.getMethodConfigurations(LibraryService.getInstance().getCurrentMethodLibrary())));
			return configsList.toArray();
		}
	};
	
	protected ILabelProvider labelProviderConfigs = new AdapterFactoryLabelProvider(
			TngAdapterFactory.INSTANCE
					.getNavigatorView_ComposedAdapterFactory()) {
		public String getText(Object object) {
			if (object instanceof String) {
				return (String) object;
			}
			else if (object instanceof MethodConfiguration) {
				return ((MethodConfiguration)object).getName();
			}
			else return object.toString();
		}
	};

	/**
	 * Creates a new instance.
	 */
	public ConfigurationContributionItem(IAction action) {
	}

	public void fill(ToolBar parent, int index) {
		item = new ToolItem(parent, SWT.SEPARATOR);
		Control box = createControl(parent);
		item.setControl(box);
		item.setWidth(240);
	}

	public void fill(CoolBar coolBar, int index) {
		Control box = createControl(coolBar);

		int flags = SWT.DROP_DOWN;
		if (index >= 0) {
			coolItem = new CoolItem(coolBar, flags, index);
		} else {
			coolItem = new CoolItem(coolBar, flags);
		}
		// Set the back reference.
		coolItem.setData(this);

		// Add the toolbar to the CoolItem widget.
		coolItem.setControl(box);

		// If the toolbar item exists then adjust the size of the cool item.
		Point toolBarSize = box.computeSize(SWT.DEFAULT, SWT.DEFAULT);

		// Set the preffered size to the size of the toolbar plus trim.
		coolItem.setMinimumSize(toolBarSize);
		coolItem.setPreferredSize(toolBarSize);
		coolItem.setSize(toolBarSize);
	}

	public void fill(Composite parent) {
		createControl(parent);
	}

	private Control createControl(Composite parent) {
		configCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
		configCombo.setVisibleItemCount(10);
		configCombo.setEnabled(true);
		configComboViewer = new ComboViewer(configCombo);
		configComboViewer.setContentProvider(contentProviderConfigs);
		configComboViewer.setLabelProvider(labelProviderConfigs);
		configComboViewer.setInput(LibraryService.getInstance().getCurrentMethodLibrary());


		configComboViewer.addPostSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				performSelectionChanged();
			}
		});
		
		String savedConfigName = getSavedLastConfig();
		MethodConfiguration savedConfig = LibraryServiceUtil.getMethodConfiguration(
				LibraryService.getInstance().getCurrentMethodLibrary(), savedConfigName);
		if (savedConfig != null) {
			configComboViewer.setSelection(new StructuredSelection(savedConfig));
		}
		else {
			configComboViewer.setSelection(new StructuredSelection(SELECT_CONFIGURATION));
		}
		
		libSvcListener = new ILibraryServiceListener() {

			public void configurationSet(MethodConfiguration config) {
				selectConfiguration(config);
			}

			public void libraryClosed(MethodLibrary library) {
			}

			public void libraryCreated(MethodLibrary library) {
				refresh();
			}

			public void libraryOpened(MethodLibrary library) {
				refresh();
			}

			public void libraryReopened(MethodLibrary library) {
				refresh();
			}

			public void librarySet(MethodLibrary library) {
				refresh();
			}
			
		};
		LibraryService.getInstance().addListener(libSvcListener);
		
		return configCombo;
	}

	private static MethodConfiguration getCurrentSelectedConfig() {
		IStructuredSelection selection = (IStructuredSelection) configComboViewer.getSelection();
		Object object = selection.getFirstElement();
		if (object instanceof MethodConfiguration) {
			return (MethodConfiguration)object;
		}
		return null;
	}
	
	private static String getCurrentSelectedConfigName() {
		IStructuredSelection selection = (IStructuredSelection) configComboViewer.getSelection();
		Object object = selection.getFirstElement();
		if (object != null && object instanceof MethodConfiguration) {
			return ((MethodConfiguration)object).getName();
		}
		if (object instanceof String)
			return (String)object;
		return ""; //$NON-NLS-1$
	}

	
	private static void performSelectionChanged() {
		MethodConfiguration config = getCurrentSelectedConfig();
		if (config != LibraryService.getInstance().getCurrentMethodConfiguration()) { 
			LibraryService.getInstance().setCurrentMethodConfiguration(config);
		}
		saveSelectedConfigIntoPersistence();
		refresh();
	}

	private static void saveSelectedConfigIntoPersistence() {
		IPreferenceStore store = LibraryPlugin.getDefault()
				.getPreferenceStore();
		store
				.setValue(
						LibraryPreferenceConstants.PREF_SELECTED_CONFIG_IN_LAST_SESSION,
						getCurrentSelectedConfigName());
		LibraryPlugin.getDefault().savePluginPreferences();
	}

	private static String getSavedLastConfig() {
		IPreferenceStore store = LibraryPlugin.getDefault()
				.getPreferenceStore();
		return store
				.getString(LibraryPreferenceConstants.PREF_SELECTED_CONFIG_IN_LAST_SESSION);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.action.ContributionItem#dispose()
	 */
	public void dispose() {
		if(libSvcListener != null) {
			LibraryService.getInstance().removeListener(libSvcListener);
		}
		configCombo.dispose();
		super.dispose();
	}
	
	public static void refresh() {
		configComboViewer.refresh();
	}
	
	public static void selectConfiguration(MethodConfiguration config) {
		if (config != null && config == getCurrentSelectedConfig())
			return;
		if (config != null) {
			configComboViewer.setSelection(new StructuredSelection(config));
		}
		else {
			// config is null, so select the "Select a configuration item"
			// first refresh list so that the "Select a config.." string gets added to the list
			refresh();
			configComboViewer.setSelection(new StructuredSelection(SELECT_CONFIGURATION));
		}
	}

}