/**
 *  DivPlus Types accessory
 *  Part of DivPlus (http://divplus.novomancy.org/)
 *
 *  Functions to allow easy management of groups of DivPlus divs.  Types are identified
 *  by a name string which is associated with a DivPlus object.  A DivPlus object can have
 *  0, 1, or many types associated with it.  Each DivPlus object stores its own types in the
 *  [DivPlusObject].typeArray array, and a list of all DivPlus objects of a given type can be
 *  found in the global DivPlus.globalTypeArray[typeName].  Functions for using types are either
 *  prototyped into the DivPlus object itself or can be found under DivPlus.types.[functionName].
 *  See the individual functions for more information.
 *
 *  @author john.bell@REMOVEME.umit.maine.edu
 *  @version 0.1.20040526
 *  @uses defined.js
 *  @uses divplus.js
 *
 */

DivPlus.globalTypeArray = new Array();
DivPlus.types = new Array();

/**
 * DivPlus.addType mutator
 * Adds [newType] to the list of this div's types.
 *
 * @argument	newType		variable		Either a single string or an array of strings
 *											defining the type(s) of the div.
 */
DivPlus.prototype.addType = function(newType){
	if(defined(newType)=="object"){
		for(var i=0; i<newType.length; i++){
			if(!defined(DivPlus.globalTypeArray[newType[i]])) DivPlus.globalTypeArray[newType[i]] = new Array();
			DivPlus.globalTypeArray[newType[i]][this.objectID] = this;
			this.typeArray[newType[i]] = true;
		}
	} else {
		if(!defined(DivPlus.globalTypeArray[newType])) DivPlus.globalTypeArray[newType] = new Array();
		DivPlus.globalTypeArray[newType][this.objectID] = this;
		this.typeArray[newType] = true;
	}
}

/**
 * DivPlus.removeType mutator
 * Removes [removedType] from the list of this div's types.
 *
 * @argument	removedType	str		Either a single string or an array of strings
 *									defining the type(s) to be removed from the div.
 */
DivPlus.prototype.removeType = function(removedType){
	if(defined(removedType)=="object"){
		for(var i=0; i<removedType.length; i++){
			if(defined(this.typeArray[removedType[i]])){
				if(defined(DivPlus.globalTypeArray[removedType[i]][this.objectID])) delete DivPlus.globalTypeArray[removedType[i]][this.objectID];
				delete this.typeArray[removedType[i]];
			}
		}
	} else {
		if(defined(this.typeArray[removedType])){
			if(defined(DivPlus.globalTypeArray[removedType][this.objectID])) delete DivPlus.globalTypeArray[removedType][this.objectID];
			delete this.typeArray[removedType];
		}
	}
}

/**
 * DivPlus.setType mutator
 * Removes any current types from the div and replaces them with [newType]
 *
 * @argument	newType		variable	Either a single string or an array of strings
 *										defining the new type(s) of the div.
 */
DivPlus.prototype.setType = function(newType){
	for(removedType in this.typeArray)	this.removeType(removedType);
	if(defined(newType)=="object"){
		for(var i=0; i<newType.length; i++) this.addType(newType[i]);
	} else {
		this.addType(newType);
	}
}

/**
 * DivPlus.changeType mutator
 * Changes a div from type [oldType] to type [newType].  If the div has multiple
 * types, other types are not affected.
 *
 * @argument	oldType		str		Type to change from
 * @argument	newType		str		Type to change to
 */
DivPlus.prototype.changeType = function (oldType, newType){
	this.removeType(oldType);
	this.addType(newType);
}

/**
 * DivPlus.getType accessor
 * Returns an array of the types associated with this div
 *
 * @returns an array of this div's types.
 */
DivPlus.prototype.getType = function(){
	var types = new Array();
	for(typeName in this.typeArray) types.push(typeName);
	return types;
}

/**
 * DivPlus.isType accessor
 * Determines whether or not this div is of type [keyType]
 *
 * @argument	keyType		variable	Either a single string or an array of strings
 *										which may be associated with the div
 * @returns true if the div is of type [keyType] (or any one of the strings in [keyType] if [keyType]
 *		    is an array), otherwise false.
 */
DivPlus.prototype.isType = function(keyType){
	if(defined(keyType)=="object"){
		for(var i=0; i<keyType.length; i++){
			if(defined(this.typeArray[keyType[i]])) return true;
		}
	} else if(defined(this.typeArray[keyType])) return true;
	return false;
}

/**
 * DivPlus.types.getTypes
 * Returns an array of the DivPlus objects matching type [keyType]
 * If keyType is an array, getTypes returns objects which match any type
 * in [keyType].
 *
 * @argument	keyType		variable	Either a single string or an array of strings
 *										which may be associated with the divs to be returned
 * @returns	an array of DivPlus objects of type [keyType], or an empty array if there are no matches.
 */
DivPlus.types.getTypes = function(keyType){
	if(defined(keyType)=="object"){
		var matches = new Array();
		for(var i=0; i<keyType.length; i++){
			if(defined(DivPlus.globalTypeArray[keyType[i]])){
				for(divID in DivPlus.globalTypeArray[keyType[i]]){
					matches[divID] = DivPlus.globalTypeArray[keyType[i]][divID];
				}
			}
		}
		return matches;
	}
	if(defined(DivPlus.globalTypeArray[keyType])) return DivPlus.globalTypeArray[keyType];
	return new Array();
}

/**
 * DivPlus.types.getTypesAnd
 * Returns an array of the DivPlus objects matching all types in [keyType]
 *
 * @argument	keyType		arr			Array of types which much be matched
 * @returns an array of DivPlus objects which are associated with all types 
 *          listed in [keyType], or an empty array if nothing matches.
 */
DivPlus.types.getTypesAnd = function(keyType){
	var matches = new Array();
	for(var i=0; i<keyType.length; i++){
		if(!defined(DivPlus.globalTypeArray[keyType[i]])) return new Array();
		for(divID in DivPlus.globalTypeArray[keyType[i]]){
			matches[divID] = DivPlus.globalTypeArray[keyType[i]][divID];
		}
	}
	for(divID in matches){
		for(var i=0; i<keyType.length; i++){
			if(!defined(matches[divID].typeArray[keyType[i]])){
				delete matches[divID];
				break;
			}
		}
	}
	return matches;
}

/**
 * DivPlus.types.changeType
 * Changes all divs of type [oldType] to type [newType].  If the divs had
 * multiple types, and types other than [oldType] remain as they were.
 *
 * @argument	oldType		str			Type of divs to change the types of
 * @argument	newType		str			Type to change to
 */
DivPlus.types.changeType = function(oldType, newType){
	if(defined(DivPlus.globalTypeArray[oldType])){
		for(divID in DivPlus.globalTypeArray[oldType]){
			DivPlus.globalTypeArray[oldType][divID].changeType(oldType, newType);
		}
	}
}		