/**
 * @classDescription Vivieb.LinksManager
 * this class allows to give one or more <div> or <span> tags a common 
 * "linked text" behavior through the creation and the management of 
 * related "link" objects.
 * All the managed links share the same behaviors and the same event handlers.
 *  
 * Requires: class.js, jquery.js, jquery.vivieb.js
 * 
 * Link object
 * -------------
 * A link object has the following properties:
 * 
 * element {DOM Element}
 * 	the DOM Element object related to the tag that implements the link
 *  (a, span or div depending on the type option in its links manager)
 * 
 * styles {integer}
 * 	identifier in its links manager for the styles set used to render the link 
 * 
 * selected {boolean}
 * 	the current state of the link. Only defined for "selectable" links 
 * 
 * disabled {boolean}
 * 	true, if the link is currently disabled
 * 
 * group {integer}
 * 	identifier in its links manager for the group that owns the link.
 * 	Only defined for "selectable" links.
 * 
 * params {object}
 * 	data object linked to the link
 * 
 * 
 * Links Manager Callbacks
 * -------------------------
 * 
 * The context (this) of all callbacks is set to the link manager instance 
 * that owns the link that originates the event. The callbacks are:
 * 
 * onClick, onMouseOver, onMouseOut, onMouseDown, onMouseUp {function}:
 * 	invoked after the corresponding event on the span or div that implements
 *  the link. The onClick callback is implemented only for "simple" and "stripe"
 *  type. 
 *  The parameters to this callback are (in order):
 * 		link {object}
 * 			the link object that originates the event
 * 		event {object}
 * 			the jQuery event object. For the onClick callback, this parameter
 * 			is undefined if the callback is invoked due to a "click" method 
 * 			call. 
 * 		
 * onBeforeSelect {function}:
 * 	invoked before the selection of a "selectable" link. The function can return
 * 	false to cancel the selection.  
 * 	The parameters to this callback are (in order):
 * 		link {object}: 
 * 			the link object being selected
 *		unselecting {object}: 
 *			the link object being unselected, if any. Otherwise, null.
 * 
 * onUnselect {function}
 * 	invoked after a "selectable" link has been unselected (after selecting 
 * 	another one).
 * 	The unique parameter to these callbacks is:
 * 		link {object}
 * 			the link object that has been unselected
 * 
 * 
*/

(function($) {


Vivieb._LinksManager = {
	/**
	 * @constructor Vivieb.LinksManager
	 *
	 * @param options {Object}
	 *	object that specifies the options for the class behavior through 
	 * 	its properties. These are:
	 *
	 * (Required)
	 *
	 * id {string}:
	 * 	Unique identifier for the links manager object. It's used as
	 * 	the common prefix to name the span or div tags that implement the 
	 * 	managed links.
	 * 	Default: "lnkmng"
	 *
	 * type {string}:
	 * 	the type of link managed by the instance. Possible values are:
	 * 		"link"	:	classic link implemented with <a> tag without the 
	 * 					onClick callback (only navigation).
	 * 		"simple":	link simulation with a onClick callback (no navigation). 
	 * 					The link's width adapts to its content.
	 * 					Implementated with <span> tag.
	 * 		"stripe":	link simulation with a onClick callback (no navigation). 
	 * 					the link's width adapts to its parent node.
	 * 					Implementated with <div> tag.
	 * 	Default: "simple"
	 *
	 * (Optional)
	 *
	 * disabled {boolean}:
	 * 	if true, every new link is added in the disabled state
	 *
	 * rollover {boolean}:
	 * 	if true, the rollover effect is enabled on the default render styles set.
	 *
	 * selectable {boolean}:
	 * 	if true, the links created will be put in a group and will be
	 * 	provided with a double state (unselected/selected). Only one link
	 *  per group can be selected. This options is valid only for "simple" and 
	 *  "stripe" type
	 *
	 * style {object}:
	 * 	object that specifies through its properties the CSS properties
	 * 	for every span or div tag that implements a new added link.
	 *
	 * */
	initialize: function(options){
		var instance = this;
		instance.impl = Vivieb._LinksManagerImpl;
		var impl = instance.impl;
		instance.links = [];
		instance.nId = 0;
		impl._setOptions(instance, options);
		instance.rss = impl._initRSS(instance.options.rollover);
		instance._click = instance._dblclick = impl._getClickHandler(instance);
		instance._mouseover = impl._getMouseoverHandler(instance);
		instance._mouseout = impl._getMouseoutHandler(instance);
		instance._mousedown = impl._getMousedownHandler(instance);
		instance._mouseup = impl._getMouseupHandler(instance);
		$(window).unload(impl._destroy(instance));
	},
	
	/**
	 * @method $
	 * 	searches for the link objects based on the search criteria specified
	 * 	with the key and searchField parameters
	 * 
	 * @param {Object} key
	 * 	the data to search for
	 * 
	 * @param {Object} searchField
	 * 	where to search for key. If not defined, the search is performed directly
	 * 	on the params property of every link object managed by this instance.
	 * 	If defined, the method assumes that the params property	of the blinkutton 
	 * 	objects references to an object. In that case, the searchField must indicate 
	 * 	the name of the object property which to perform the search on.
	 * 
	 *  @return {object, array of object}
	 *  an array of all the link objects matching the search criteria, or a single
	 *  link object if there is only one match. null, if no link is found.
	 */
	findKey: function(key, searchField){
	 	var links = this.links;
	 	var rslt = [];
	 	for(var i=0, ln=links.length; i<ln; i++) {
	 		var link = links[i];
	 		if(searchField) {
				if(link.params[searchField] == key) rslt.push(link);
			}
	 		else if(link.params == key) rslt.push(link);
	 	}
	 	var ln = rslt.length;
	 	if(ln == 0) return null;
	 	if(ln == 1) return rslt[0];
	 	return rslt;
	},
	
	/**
	 * @method build
	 * create new managed link objects without adding them in the DOM tree.
	 *
	 * @param options {Object}
	 *	object that specifies the options for the creation of the new links
	 *	These are:
	 * 
	 * alwaysClick {boolean}
	 * 	This option is only valid for a selectable link. If true, the click
	 * 	event will be triggered even if the link is already selected. 
	 * 	Otherwise, the click event will never be fired if the link is 
	 * 	already selected.
	 * 
	 * attributes {object}:
	 *  object that specifies through its properties the attributes
	 *  that will be assigned to the span or div tag that implements the link.
	 * 
	 * disabled {boolean}:
	 * 	if true, the link will be created in the disabled state (all the callbacks
	 * 	are disabled). This option ovveride the "disabled" instance option.
	 *
	 * group {string}:
	 * 	the name of the group that owns the link. This option is valid
	 * 	only for the "selectable" links. If not specified, the link will be
	 * 	assigned to the default group.
	 *
	 * dom {DOM Element, string}: 
	 * 	if specified, indicates the existing DOM a, span or div element 
	 * (depending on the "type" instance option) to use to implement the links. 
	 *  It can be a DOM Element reference or a valid jQuery selector. 
	 *  A link object will be created for every tag found and stored in the 
	 *  manager. If no tag will be found or if this property is not defined, 
	 *  only one link object will be created and a new DOM element will be 
	 *  created to render the link.
	 *
	 * params {object}:
	 * 	it can be any kind of data. This value will be assigned to the
	 * 	params property of every new link object created
	 *
	 * renderSet {string}:
	 * 	the name of the render styles set to use to render the link. If not
	 * 	specified, the default render styles set will be used.
	 * 
	 * style {object}:
	 * 	object that specifies through its properties the CSS properties for the
	 * 	span or div tag that implements the created link. If specified, they will be
	 * 	added to those ones specified in the manager instance.
	 *
	 * @return {array of object}
	 * an array containing the link objects that acts for every link created.
	 * */
	build: function(options){
		var instance = this;
		var o = instance.options;
		var links = [];
		
		var elemType;
		switch(o.type) {
			case 'link': elemType = 'a'; break;
			case 'simple': elemType = 'span'; break;
			case 'stripe': elemType = 'div'; break;
		};
		var elem;
		if (options.element)
			elem = $(options.dom).filter(function() {
				return this.nodeName.toLowerCase() == elemType;
			});
		if (!elem || elem.length == 0) 
			elem = $('<' + elemType + '></' + elemType + '>');
		elem.each(function(){
			this.id = o.id + '_' + instance.nId++;
			var rs = $.vv_indexOfKey(instance.rss, 'name', options.renderSet);
			if(rs == -1) rs = 0;
			var link = {
				element: this,
				rs: rs,
				disabled: options.disabled != undefined ? options.disabled : o.disabled
			};
			if (options.alwaysClick)
				link.alwaysClick = options.alwaysClick; 
			if (options.params) 
				link.params = options.params;
			if (o.selectable) 
				if (!options.group) 
					link.group = 0;
				else {
					var groupPos = $.vv_indexOfKey(instance.grps, 'name', options.group);
					if (groupPos != -1) 
						link.group = groupPos;
					else {
						instance.grps.push({
							name: options.group
						});
						link.group = instance.grps.length - 1;
					}
				}
			links.push(link);
			instance.links.push(link);
		})
		.css($.extend({}, o.style ||{}, options.style || {}, {
				cursor: options.disabled ? '' : 'pointer'
			}
		))
		.attr(options.attributes || {})
		.bind('mousedown.' + o.id, instance._mousedown)
		.bind('mouseup.' + o.id, instance._mouseup)
		.hover(instance._mouseover, instance._mouseout);
		if(o.type != 'link') {
		elem
			.bind('click.' + o.id, instance._click)
			.bind('dblclick.' + o.id, instance._click)
		};
		
		return links;
	},
	
	/**
	 * @method clear
	 * 	remove all the link objects from the manager and all the related
	 * 	span or div tags from the DOM tree. The render styles set is cleaned 
	 * 	based on the clearRSS parameter's value.
	 * 
	 */
	clear: function(clearRSS){
		var instance = this;			
 		instance.remove(instance.links);
 		instance.nId = 0;
		if (clearRSS) 
 			instance.rss = instance.impl._initRSS(instance.options.rollover); 
	},
	
	/**
	 * @method click
	 * 	this method acts like a mouse click has occured on the span or div tag 
	 * 	with the id attribute equal to linkId parameter. Calling this method
	 * 	on a "link" type has no effect (no navigation). 
	 *  For the other types, the effects differs depending on the "selectable"
	 *  behavior:
	 * 		"not selectable":
	 * 			the onClick callback is invoked, if defined
	 * 		"selectable":
	 * 			all the following procedure occurs only if the link is not
	 * 			already selected:
	 * 			- the onBeforeSelect callback is invoked, if defined. 
	 * 			- if the callback function doesn't cancel the selection: 
	 * 				- the link is selected
	 * 				- the potential already selected link into the same group
	 * 				  is unselected
	 * 				- if such a link exists, the onUnselect callback is 
	 * 				  invoked, if defined. 
	 *	 			- the onClick callback is invoked, if defined.
	 * 			 
	 * @param {string} linkId
	 *  the id attribute value of the span or div tag pretending to be clicked
	 *  Obviously, the DOM element must already be managed by this manager. 
	 */
	
	click: function(linkId){
		var instance = this;
		var link = instance.impl._$(instance.links, linkId);
		if(!link || link.disabled || instance.options.types == 'link') 
			return;
		var style = link.element.style;
		var cursor = style.cursor; 
 		style.cursor = 'wait';
 		try {
			if (instance.options.selectable) {
				if (!link.selected || link.alwaysClick) {
					var group = instance.grps[link.group];
					var unselecting = group.selected;
					var trigger = true;
					if (typeof instance.onBeforeSelect == 'function') 
						trigger = instance.onBeforeSelect.call(instance, link, unselecting || null) != false;
					if (trigger) {
						if (unselecting && unselecting != link) {
							unselecting.selected = false;
							instance.impl._render(instance, unselecting, 1);
							unselecting.element.style.cursor = 'pointer';
							if (typeof instance.onUnselect == 'function') 
								instance.onUnselect.call(instance, unselecting);
						}
						if (!link.selected) {
							link.selected = true;
							group.selected = link;
							instance.impl._render(instance, link, 2);
							cursor = '';
						}
						if (typeof instance.onClick == 'function') 
							instance.onClick.call(instance, link, arguments[1]);
					}
				}
			}
			else if (typeof instance.onClick == 'function') 
				instance.onClick.call(instance, link, arguments[1]);
 		}
 		catch(e) {throw e;}
 		finally {
 			style.cursor = cursor;
 		}
 	},
	
	/**
	 * @method disable
	 * 	disable the links identified by the who and target parameters
	 * 
	 * @param {Object, Array of Object, string} who
	 * specify the link objects (or a single link object) to disable.
	 * If not defined, it specifies all the managed links.
	 * The link set to disable can also be identified through one of the
	 * following string:
	 * 	"all"	: all the managed links (like undefined).
	 * 	"renderSet"	: 
	 * 			  all the links with a specified render styles set. His name 
	 * 			  is given by the "target" parameter. 
	 * 	"group"	: all the selectable links owned by a specified group. The 
	 * 			  group name is given by the "target" parameter. To disable
	 * 			  the default group, don't specify the "target" parameter. 
	 * 	
	 * @param {string} target
	 * 	the meaning of this parameter depends on the "who" parameter's value.
	 * 	Specify it only when required.
	 */
	disable: function(who, target){
		var instance = this;
		instance.impl._enable(instance, who, target, instance.impl._disableLink);
	},

	/**
	 * @method enable
	 * 	enables the links identified by the who and target parameters
	 * 
	 * @param {Object, Array of Object, string} who
	 * 	see the disable method.
	 * @param {string} target
	 * 	see the disable method.
	 */
	enable: function(who, target){
		var instance = this;
		instance.impl._enable(instance, who, target, instance.impl._enableLink);
	},

	/**
	 * @method getGroup
	 * 	returns the group object specified by the parameter id.
	 * 	
	 * @param {integer} id
	 *  the group identifier. It can be given by the group property of the 
	 *  link object.
	 *  
	 * @return {object}
	 *  the group object corresponding to the id parameter or undefined if
	 *  the group doesn't exist. The method returns null if the link is not
	 *  "selectable".
	 *  A group object has the following properties:
	 *  	"name" {string}: 
	 *  		the name of the group. This property is not defined for the
	 *  		default group (id=0)
	 *  	"selected" {integer}:
	 *  		the internal identifier of the potential link object currently 
	 *  		selected for the group. The selected link object can be 
	 *  		obtained through:	instance.links[selected].
	 * 
	 */
	getGroup: function(id){
		var instance = this;
		if(!instance.options.selectable) return null;
 		return instance.grps[id];
	},
	
	/**
	 * @method insert
	 * insert one or more managed links in the DOM tree. The managed links
	 * can already exist or can be created depending on the options passed
	 * as the argument.
	 *
	 * @param options {Object}
	 * object that specifies (through its properties) the options for the
	 * (potential) creation of the links and theirs insertion in the DOM
	 * tree. These are:
	 *
	 * links {array of object,object}:
	 * 	the array of link objects (or a single link object) resulting
	 * 	from a previous creation with the "build" or "insert" methods.
	 * 	This option is used only to insert already existing links. If
	 * 	the link is already inserted in the DOM tree, it will be moved 
	 * 	to its new position.
	 *
	 * As an alternative, if the link doesn't exist, the "options" argument
	 * must specify all the options expected by the "build" method for
	 * the link's creation.
	 * In both cases, the "options" argument must specify the options that
	 * serve the purpose to position the link in the DOM tree, that are:
	 *
	 * target {DOM object, string}:
	 * 	the DOM element that will be refered to insert the link.
	 * 	It can be a DOM object reference or a valid jQuery selector.
	 * 	If more than one target are found with a jQuery selector, only
	 * 	the first one will be the target.
	 *
	 * position {string}:
	 * 	the position where to insert the link in respect to the
	 * 	"target" element. It can be one of these values:
	 * 		"prepend":	the link will be inserted before the content
	 * 					of "target".
	 * 		"append":	the link will be inserted after the content
	 * 					of "target".
	 * 		"before":	the link will be inserted before "target".
	 * 		"after":	the link will be inserted after "target".
	 * 	Default: "append"
	 *
	 * These options can be omitted if all the span or div tags that implement
	 * the links are already inserted. In tath case, the insert method
	 * only renders the indicated links in their current position.
	 *
	 * @return {array of object}
	 * an array containing the link objects that acts for every link inserted.
	 *
	 * */
	insert: function(options){
		if (!options) 
			return null;
		var instance = this;
		var links = options.links;
		if (links) {
			if (links.length == undefined) 
				links = [links];
		}
		else 
			links = this.build(options);
		if (options.target) 
			try {
				instance.toJQuery(links).vv_insert(options.target, options.position);
			} 
			catch (e) {
				$.vv_exception(instance, e);
			}
		for (var i = 0, ln = links.length; i < ln; i++) {
			var link = links[i];
			if (!link.element.parentNode) 
				$.vv_exception(instance, {name: 'ParentNodeMissing'}, link.element.id);
			instance.impl._render(instance, link, 1);
		}
		return links;
	},
	
	/**
	 * @method remove
	 * 	removes the given link objects from the manager. The related
	 * 	img tags are also removed from the DOM tree.
	 * 
	 * @param {Object, Array of Object} links
	 * 	the link objects (or a single object) to remove.
	 */
	remove: function(links){
		if(!links) return null;
		var instance = this;
		if(isNaN(links.length)) links = [links];
		for(var i=links.length-1; i>=0; i--) {
 			var link = links[i];
 			if(instance.options.selectable) {
 				var group = instance.grps[link.group];
 				if(group.selected == link) group.selected = null;
 			}
 			$(link.element).remove();
 			link.element = null;
 			link.params = null;
 			$.vv_removeItem(instance.links, link);
 		}
	},

	/**
	 * @method setRenderStyles
	 * allows to add or modify a render styles set in the manager.
	 * A render styles set is used by the manager for links rendering. A
	 * set indicates the CSS properties to apply for all possible link's
	 * state.
	 * 
	 * @param {string} name
	 * 	the name that identifies the render styles set. This name must be 
	 * 	used as the "renderSet" option value when creating the link.
	 * 	Don't specify the name parameter to modify the default render
	 * 	styles set.  
	 * 
	 * @param {string} state
	 * 	the particular state to be set with the styles properties. It can
	 * 	be one of the following:
	 * 		"disabled":	when the link is disabled (it doesn't fire events)
	 * 		"normal":	when the link is enabled
	 * 		"over":		when the link is enabled and the mouse is over it
	 * 		"selected": when the link is enabled and in the "selected"
	 * 					state. If the link is not selectable, this state
	 * 					last only during the click event. If the link is
	 * 					selectable, this state last until another link is
	 * 					selected
	 * 
	 * @param {Object} styles
	 * 	specifies through its properties the CSS properties to apply when
	 * 	the link is in the specified state. These styles extend the already
	 * 	existing styles on the span or div DOM element that implements the 
	 * 	link. If undefined or false, no styles will be applied in the 
	 * 	specified state.
	 * 	
	 */
	setRenderStyles: function(name, state, styles) {
		var instance = this;
		var iState = instance.impl._indexOfState(state);
		if(iState == -1) return;
		var rs = instance.impl._getRenderSet(instance.rss, name);
		var states = rs.states;
		if(styles)
			states[iState] = {
				styles: $.extend({}, styles || {})
			};
		else
			delete states[iState];
	},

	
	/**
	 * @method toJQuery
	 * 	obtains a jQuery wrapped set containing the span or div elements used to 
	 *  render the given managed links.
	 * 
	 * @param {Object, Array of Object} links
	 * 	the link objects (or a single object) which to obtain the wrapped
	 * 	set from. If not specified, all the managed links will be considered.
	 */
	toJQuery: function(links){
		var instance = this;
		if (links == undefined) links = instance.links;
		else if(isNaN(links.length)) links = [links];
		return $($.map(links, function(link){
			return link.element;
		}));
	},
	
	toString: function(){
		var instance = this;
		return 'LinksManager (id: ' + instance.options.id + ')';
	}
	
};

Vivieb._LinksManagerImpl = {
	
	exception: {
		ParentNodeMissing: 'Parent node missing inserting link \'{0}\'!'
	},
	
	_$:function(links, linkId) {
		for(var i=0, ln=links.length; i<ln; i++)
			if(links[i].element.id == linkId) return links[i];
	},
	
	_destroy: function(instance) {
		return function(){
			instance.clear(true);
			instance._click = null;
			instance._dblclick = null;
			instance._mouseover = null;
			instance._mouseout = null;
			instance._mousedown = null;
			instance._mouseup = null;
		}
	},
	
	_disableLink: function(instance, link){
		if(link.disabled) return;
		link.disabled = true;
		instance.impl._render(instance, link);
		link.element.style.cursor = '';
	},
	
	_enable: function(instance, who, target, enableMethod){
		if(!who) who = 'all';
		var links = instance.links;	
		switch(who) {
			case 'all':
				for(var i=0, ln=links.length; i<ln; i++) 
					enableMethod(instance, links[i]);
				break;
			case 'renderSet':
				if(!target) return;
				var rs = $.vv_indexOfKey(instance.rss, 'name', target);
				if(rs == -1) return;
				for(var i=0, ln=links.length; i<ln; i++) {
					var link = links[i];
					if(link && link.rs == rs) enableMethod(instance, link);
				}
				break;
			case 'group':
				if(!instance.options.selectable) return;
				var group = 0;
				if(target) {
					group = $.vv_indexOfKey(instance.grps, 'name', target);
					if(group == -1) return;
				}
				for(var i=0, ln=links.length; i<ln; i++) {
					var link = links[i];
					if(link && link.group == group) enableMethod(instance, link);
				}
				break;
			default:
				if(isNaN(who.length)) who = [who];
				for(var i=0, ln=who.length; i<ln; i++)
					enableMethod(instance, who[i]);
		}
	},

	_enableLink: function(instance, link){
		if(!link.disabled) return;
		delete link.disabled;
		var selected = link.selected;
		instance.impl._render(instance, link, selected ? 2:1);
		link.element.style.cursor = !selected || link.alwaysClick ? 'pointer' :  '';
	},
	
	_getClickHandler: function(instance) {
		return function(event) {
			if(event.target != this)
				return;
			instance.click(event.target.id, event);
			event.stopPropagation();
		}
	},
	
	_getMousedownHandler: function(instance) {
		return function(event){
			if(event.target != this)
				return;
			var link = instance.impl._$(instance.links, event.target.id);
			if(!link || link.disabled) 
				return;
			if(!instance.options.selectable)
				instance.impl._render(instance, link, 2);
			if(typeof instance.onMouseDown == 'function')
				instance.onMouseDown.call(instance, link, event);
			event.stopPropagation();
		}
	},

	_getMouseoutHandler: function(instance) {
		return function(event){
			if(event.target != this)
				return;
			var link = instance.impl._$(instance.links, event.target.id);
			if(!link || link.disabled) 
				return;
			if(!link.selected || link.alwaysClick)
				instance.impl._render(instance, link, link.selected ? 2 : 1);
			if(typeof instance.onMouseOut == 'function')
				instance.onMouseOut.call(instance, link, event);
			event.stopPropagation();
		}
	},
	
	_getMouseoverHandler: function(instance) {
		return function(event){
			if(event.target != this)
				return;
			var link = instance.impl._$(instance.links, event.target.id);
			if(!link || link.disabled) 
				return;
			if(!link.selected || link.alwaysClick)
				instance.impl._render(instance, link, 3);
			if(typeof instance.onMouseOver == 'function')
				instance.onMouseOver.call(instance, link, event);
			event.stopPropagation();
		}
	},
	
	_getMouseupHandler: function(instance) {
		return function(event){
			if(event.target != this)
				return;
			var link = instance.impl._$(instance.links, event.target.id);
			if(!link || link.disabled) 
				return;
			if(!instance.options.selectable)
				instance.impl._render(instance, link, 1);
			if(typeof instance.onMouseUp == 'function')
				instance.onMouseUp.call(instance, link, event);
			event.stopPropagation();
		}
	},
	
	_getRenderSet: function(rss, name) {
		var rsPos = 0;
		if(name) {
			rsPos = $.vv_indexOfKey(rss, 'name', name);
			if(rsPos == -1) {
				rss.push({name: name, states: []});
				rsPos = rss.length - 1;
			}
		}
		return rss[rsPos];
	},
	
	_indexOfState: function(state) {
		return ['disabled', 'normal', 'selected', 'over'].indexOf(state);
	},

	
	_initRSS: function(rollover) {
		var rss = [{states: [
				{styles: {color: '#eeeeee'}}, 
				{styles: {color: ''}}, 
				{styles: {color: '#ff6600'}}
			]}];
		if(rollover)
			rss[0].states[3] = {styles: {color: '#0066ff'}};
		return rss;
	},
	
	_render: function(instance, link, nState) {
		if(link.disabled) nState = 0;
		var rs = instance.rss[link.rs];
		if(nState == 1 && link.selected) nState = 2;
		var state = rs.states[nState];
		if(!state && nState == 3) state = rs.states[1];
		if(!state) return;
		$(link.element).css(state.styles || {});
	},
	
	_setOptions: function(instance, options) {
		var o = instance.options = $.extend(true, {
			id		: 'lnkmng',
			type	: 'simple',
			disabled: false
		}, options || {});
		if(o.selectable)
			instance.grps = [{name: null}];
	}
	
};

Vivieb.LinksManager = new Class(Vivieb._LinksManager);

})(jQuery);