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

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.common.EventManager;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.navigator.IExtensionStateModel;

/**
 *
 *
 * @since 3.2
 * @see IExtensionStateModel
 */
public class ExtensionStateModel extends EventManager implements
		IExtensionStateModel {

	private final String id;

	private final String viewerId;

	private final Map values = new HashMap();

	/**
	 * Create an extension state model for the given extension (anId) associated
	 * with the given viewer (aViewerId).
	 *
	 * @param anId
	 *            The id of the extension this state model is used for.
	 * @param aViewerId
	 *            The id of the viewer this state model is associated with.
	 */
	public ExtensionStateModel(String anId, String aViewerId) {
		id = anId;
		viewerId = aViewerId;
	}

	@Override
	public String getId() {
		return id;
	}

	@Override
	public String getViewerId() {
		return viewerId;
	}

	@Override
	public String getStringProperty(String aPropertyName) {
		return (String) values.get(aPropertyName);
	}

	@Override
	public boolean getBooleanProperty(String aPropertyName) {

		Boolean b = (Boolean) values.get(aPropertyName);
		return b != null ? b.booleanValue() : false;
	}

	@Override
	public int getIntProperty(String aPropertyName) {
		Integer i = (Integer) values.get(aPropertyName);
		return i != null ? i.intValue() : -1;
	}

	@Override
	public void setStringProperty(String aPropertyName, String aPropertyValue) {
		String oldValue = (String) values.get(aPropertyName);
		String newValue = aPropertyValue;
		if (hasPropertyChanged(oldValue, newValue)) {
			values.put(aPropertyName, newValue);
			firePropertyChangeEvent(new PropertyChangeEvent(this,
					aPropertyName, oldValue, newValue));
		}
	}

	@Override
	public void setBooleanProperty(String aPropertyName, boolean aPropertyValue) {
		Boolean oldValue = (Boolean) values.get(aPropertyName);
		Boolean newValue = aPropertyValue ? Boolean.TRUE : Boolean.FALSE;
		if (hasPropertyChanged(oldValue, newValue)) {

			values.put(aPropertyName, aPropertyValue ? Boolean.TRUE
					: Boolean.FALSE);
			firePropertyChangeEvent(new PropertyChangeEvent(this,
					aPropertyName, oldValue, newValue));
		}
	}

	@Override
	public void setIntProperty(String aPropertyName, int aPropertyValue) {
		Integer oldValue = (Integer) values.get(aPropertyName);
		Integer newValue = Integer.valueOf(aPropertyValue);
		if (hasPropertyChanged(oldValue, newValue)) {
			values.put(aPropertyName, newValue);
			firePropertyChangeEvent(new PropertyChangeEvent(this,
					aPropertyName, oldValue, newValue));
		}
	}

	@Override
	public void addPropertyChangeListener(IPropertyChangeListener aListener) {
		addListenerObject(aListener);
	}

	@Override
	public void removePropertyChangeListener(IPropertyChangeListener aListener) {
		removeListenerObject(aListener);
	}

	@Override
	public Object getProperty(String aPropertyName) {
		return values.get(aPropertyName);
	}

	@Override
	public void setProperty(String aPropertyName, Object aPropertyValue) {

		Object oldValue = values.get(aPropertyName);
		Object newValue = aPropertyValue;
		if (hasPropertyChanged(oldValue, newValue)) {
			values.put(aPropertyName, newValue);
			firePropertyChangeEvent(new PropertyChangeEvent(this,
					aPropertyName, oldValue, newValue));
		}
	}

	private boolean hasPropertyChanged(Object oldValue, Object newValue) {
		return oldValue == null || !oldValue.equals(newValue);
	}

	protected void firePropertyChangeEvent(PropertyChangeEvent anEvent) {
		Object[] listeners = getListeners();
		for (Object listener : listeners) {
			((IPropertyChangeListener) listener).propertyChange(anEvent);
		}
	}

}
