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

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Collections;

import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.value.IObservableValue;

import com.patrikdufresne.managers.ManagerEvent;
import com.patrikdufresne.managers.ManagerException;
import com.patrikdufresne.managers.databinding.ManagedObjectComputedSet;
import com.planimod.core.Employee;
import com.planimod.core.GeneratePlanifContext;
import com.planimod.core.Task;
import com.planimod.ui.PlanimodPolicy;

/**
 * This observable set provide collection of {@link Employee}. This function is
 * wrapping the function
 * {@link GeneratePlanifContext#listEmployeeByTaskProposed(Task)}.
 * 
 * @author Patrik Dufresne
 * 
 */
public class EmployeeByTaskProposedComputedSet extends ManagedObjectComputedSet {
	/**
	 * The managers.
	 */
	private GeneratePlanifContext context;

	/**
	 * Listen to planif context.
	 */
	private PropertyChangeListener listener = new PropertyChangeListener() {
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			getRealm().exec(new Runnable() {
				@Override
				public void run() {
					makeDirty();
				}
			});
		}
	};
	/**
	 * Observable employee.
	 */
	private IObservableValue task;

	/**
	 * Create a new observable set of employee.
	 * 
	 * @param context
	 *            the generate planif context
	 */
	public EmployeeByTaskProposedComputedSet(GeneratePlanifContext context,
			IObservableValue task) {
		// Avoid listening to managers events
		super(context.getManagers(), Employee.class, null,
				new IObservable[] { task });
		this.context = context;
		this.task = task;
	}

	@Override
	public synchronized void dispose() {
		super.dispose();
		this.context = null;
	}

	/**
	 * This implementation query the database to get the employees qualify for
	 * all null planif event.
	 */
	@Override
	protected Collection doList() throws ManagerException {
		if (getTask() == null) {
			return Collections.EMPTY_SET;
		}
		try {
			return this.context.getProposedTasks().employees(getTask());
		} catch (Exception e) {
			PlanimodPolicy.showException(e);
			return Collections.EMPTY_SET;
		}
	}

	/**
	 * Return the current task value or null if the observable doesn't contain
	 * an {@link Task} object.
	 * 
	 * @return the current Task or null.
	 */
	protected Task getTask() {
		if (this.task.getValue() instanceof Task) {
			return (Task) this.task.getValue();
		}
		return null;
	}

	/**
	 * This function notify this class about manager update.
	 * <p>
	 * This implementation can't determine what required to be updated in the
	 * cached, so a full update is required. to do so, the observable set is
	 * make dirty.
	 */
	@Override
	protected void notifyIfChanged(ManagerEvent event) {
		makeDirty();
	}

	@Override
	protected void startListening() {
		super.startListening();
		this.context.addPropertyChangeListener(
				GeneratePlanifContext.PROPOSED_TASKS,
				this.listener);
	}

	@Override
	protected void stopListening() {
		super.stopListening();
		this.context.removePropertyChangeListener(
				GeneratePlanifContext.PROPOSED_TASKS,
				this.listener);
	}

}