/*
 * A filterable list of elements.  FilterModel extends LinkedList,
 * and that classes' <strong>add</strong>, <strong>remove</strong>
 * and <strong>clear</strong> methods are used to manupipulate
 * FilterModel data.
 *
 * There are two methods that filter the content of the model,
 * <strong>filter</strong> and <strong>empty</strong>.
 *
 * <li><strong>filter</strong> requires a test function:</li>
 *
 * 		model.filter(function(value) {
 * 			return isAcceptable(value);
 * 		});
 *
 * (Alternatively you can pass <strong>null</strong> which is the
 * same as accepting all of the elements)
 *
 * <li><strong>empty()</strong> denies or 'hides' all the elements:</li>
 *
 * 		model.empty();
 *
 * <li>To be notified when the model has been filtered, use a
 * <strong>listener</strong> function:</li>
 *
 * 		model.addListener(function(items) { ... });
 *
 * The listener is passed a single argument which is a {@link LinkedList}
 * of the model's visible elements.
 *
 * @see LinkedList
 *
 * @author ddjohnson
 * @version 1.0
 */


function FilterModel() { }

FilterModel.prototype = new LinkedList();
FilterModel.prototype.items = new LinkedList();

FilterModel.prototype.__clear__ =
	LinkedList.prototype.clear;

/**
 * Adds a listener function. The listener is notified only when
 * the model has been filtered, not when the model data is changed
 * (by calling add or remove)
 *
 * @param l <Function>
 */
FilterModel.prototype.addListener = function(l)
{
	if(!this._listenerList)
		this._listenerList = new LinkedList();
	this._listenerList.add(l);
};

/**
 * Filter the model. The test function is expected to return true for
 * acceptable items. If the filter is null, <strong>all</strong> items
 * are accepted and no items are hidden.
 *
 * @param test <Function>, or null
 */
FilterModel.prototype.filter = function(test)
{
	this.items.clear();

	if(!test)
		test = function() { return true; };

	for(var iter = this.iterator(); iter.hasNext();)
	{
		var next = iter.next();
		if(test(next))
			this.items.add(next);
	}

	if(this._listenerList)
	{
		for(var iter = this._listenerList.iterator();
			iter.hasNext();)
		{
			iter.next()(this.items);
		}
	}
}

/**
 * Empties the model, hiding all elements.
 *
 */
FilterModel.prototype.empty = function()
{
	this.filter(function(v)
	{
		return false;
	});
}

/**
 * Removes all model data.
 *
 */
FilterModel.prototype.clear = function()
{
	this.__clear__();
	this.empty();
}

