/*
 * Copyright (c) 2011, Patrik Dufresne. All rights reserved.
 * Patrik Dufresne PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.planimod.ui.databinding;

import java.beans.PropertyChangeListener;
import java.beans.PropertyDescriptor;

import org.eclipse.core.databinding.property.INativePropertyListener;
import org.eclipse.core.databinding.property.ISimplePropertyListener;
import org.eclipse.core.databinding.property.NativePropertyListener;
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
import org.eclipse.core.internal.databinding.beans.BeanPropertyListenerSupport;

public abstract class BeanComputedValueProperty extends SimpleValueProperty {

	protected final PropertyDescriptor[] propertyDescriptors;
	protected final Class valueType;

	@SuppressWarnings("unqualified-field-access")
	protected class Listener extends NativePropertyListener implements
			PropertyChangeListener {

		protected Listener(ISimplePropertyListener listener) {
			super(BeanComputedValueProperty.this, listener);
		}

		@Override
		public void propertyChange(java.beans.PropertyChangeEvent evt) {

			if (evt.getPropertyName() != null) {
				int i = 0;
				while (i < propertyDescriptors.length
						&& !propertyDescriptors[i].getName().equals(
								evt.getPropertyName())) {
					i++;
				}
				if (i >= propertyDescriptors.length) {
					return;
				}
			}

			// Fire change
			fireChange(evt.getSource(), null);
		}

		@Override
		protected void doAddTo(Object source) {
			for (int i = 0; i < propertyDescriptors.length; i++) {
				BeanPropertyListenerSupport.hookListener(source,
						propertyDescriptors[i].getName(), this);
			}
		}

		@Override
		protected void doRemoveFrom(Object source) {
			for (int i = 0; i < propertyDescriptors.length; i++) {
				BeanPropertyListenerSupport.unhookListener(source,
						propertyDescriptors[i].getName(), this);
			}
		}
	}

	/**
	 * @param propertyDescriptor
	 * @param valueType
	 */
	public BeanComputedValueProperty(PropertyDescriptor[] propertyDescriptors,
			Class valueType) {
		this.propertyDescriptors = propertyDescriptors;
		this.valueType = valueType;
	}

	@Override
	public Object getValueType() {
		return this.valueType;
	}

	@Override
	protected void doSetValue(Object source, Object value) {
		// Not supported
		throw new UnsupportedOperationException(toString()
				+ ": Setter not supported on a converted value!"); //$NON-NLS-1$
	}

	public INativePropertyListener adaptListener(
			final ISimplePropertyListener listener) {
		return new Listener(listener);
	}
}
