/* Unit.js
 *
 *  This is an abstract class inherited by anything that interacts with the DOM other than the Page itself.
 *
 *  initSubUnit is probably the most important method here. Pass in a reference to a subunit that should
 *  be a child in the DOM, and it returns a collection of initialized subunits. E.g.:
 *  this.myEpisodeThumbnails = this.initSubUnit(BLIP.Unit.EpisodeThumbnail);
 *
 *  If you know there will /only/ be one instance of the subunit, you can immediately call .single() on the
 *  returned collection. This should, perhaps, be a different method, e.g., initSingleSubUnit. See UnitCollection
 *  for more info.
 *
 *  Implements a setContent method, which replaces the current DOM of a Unit with the DOM supplied. This
 *  is especially useful if the unit is paginated.
 *
 *
 *  Properties that must be overridden:
 *   selector : the css selector used to find elements that match the unit
 */

BLIP.Class.create("BLIP.Unit", BLIP.Object,
	function(config) {
		var thisContext = this;
		config = config || {};
		if (!config.domRoot) {
			throw new TypeError("Invalid DOM element supplied as domRoot");
		}

		BLIP.Object.call(this, config);
		this.domRoot = config.domRoot;
		this.unitCollection = {};
		this.stateChanged = new BLIP.Utils.LocalEvent("StateChange");

		$(document).ready(function() {
			if(thisContext.init) {
				thisContext.init();
			}
		});
	},

	{
		initSubUnit : function(UnitConstructor, config) {
			var thisContext = this,
					unitConfiguration = config || {},
					unitCollection = new BLIP.UnitCollection();

			this.domRoot.
				find(this.getSelectorFor(UnitConstructor)).
				each(function(i, el) {
					unitConfiguration.domRoot = $(el);
					var unit = new UnitConstructor(unitConfiguration);
					thisContext.addSubUnitEventListeners(unit);
					unitCollection.push(unit);
				});

			this.unitCollection = unitCollection;

			return unitCollection;
		},

		initSingleSubUnit : function(UnitConstructor, domRoot) {
			return new UnitConstructor({ domRoot : domRoot});
		},

		addSubUnitEventListeners : function(unit) {
			unit.stateChanged.addListener(this.childUnit_onStateChange, this);
		},

		initAdditionalSubUnits : function(collection, UnitConstructor, config) {
			var newCollection, thisContext = this;

			if (collection.constructor !== BLIP.UnitCollection) {
				newCollection = new BLIP.UnitCollection();
				newCollection.push(collection);
			}
			else {
				newCollection = collection;
			}
			$(this.domRoot)
				.find(this.getSelectorFor(UnitConstructor))
				.each(function(i, el) {
					var found = false,
							unit;

					newCollection.each(function(unit) {
						if (unit.domRoot[0] === el) {
							found = true;
						}
					});

					if (!found) {
						unit = new UnitConstructor({ domRoot : $(el)});
						thisContext.addSubUnitEventListeners(unit);
						newCollection.push(unit);
						unit.init();
					}
				});

			return newCollection;
		},

		setContent : function(content) {
			if (this.domRoot !== content) {
				var parent = this.domRoot.parent();
				this.domRoot.replaceWith(content);
				this.domRoot = parent.find(this.selector);
				this.initContents();
			}
		},

		initContents : function() {

		},

		childUnit_onStateChange : function() {
			this.stateChanged.fire();
		},

		getState : function() {
			return {};
		},

		setState : function (state) {
			return {};
		},

		getSelectorFor : function(unit) {
			if(unit) {
				return unit.prototype.selector;
			}
			else {
				throw new TypeError("No such unit. Perhaps you misspelled it, or forgot to include it?");
			}
		},
		selector : ""
	}
);

