(function() {
	
	if(typeof NK == 'undefined')
	NK = {};
	
	var log = function(msg) {
//		if(console){
//			console.log(msg);
//		}
	};

	var attachEvent = function(el, eventName, fn) {
		if (el.addEventListener) {
			el.addEventListener(eventName, fn, false);
		} else if (el.attachEvent) {
			el.attachEvent('on' + eventName, fn);
		} else {
			log("can't attach event " + eventName + " to " + el.id);
		}
		return;
	};

	var detachEvent = function(el, eventName, fn) {
		if (el.removeEventListener) {
			el.removeEventListener(eventName, fn, false);
		} else if (el.detachEvent) {
			el.detachEvent('on' + eventName, fn);
		}
	};

	var getTarget = function(ev) {
		ev = (!ev) ? window.event : ev;
		return (!ev.srcElement) ? ev.target : ev.srcElement;
	};

	var getEvent = function(ev) {
		return (!ev) ? window.event : ev;
	};

	var cancel = function(e) {
		if (e.stopPropagation) {
			e.stopPropagation();
		} else {
			e.cancelBubble = true;
		}
		return false;
	};

	/**
	 * 
	 */
	var findContainer = function(el) {
		log('findContainer');
		var c = el;
		while (c !== null && c.className.indexOf('AccumulatorContainer') == -1) {
			c = c.parentNode?c.parentNode:c.parentOffset;
		}
		log('findContainer returning ' + c.className);
		return c;
	};

	var doMoveSelected = function(from, to) {
		log('doMoveSelected: moving from ' + from.className + ' to '
				+ to.className);
		var moveFound = false;
		try {
			for ( var current = 0; current < from.options.length; current++) {
				if (from.options[current].selected) {
					moveFound = true;
					to.options[to.length] = new Option(
							from.options[current].text,
							from.options[current].value);
					from.options[current--] = null; 
				}
			}
		} catch (ex) {
			log('doMoveSelected trouble: ' + ex.message);
		}
		return moveFound;
	};

	/**
	 * 
	 */
	var doMoveAll = function(from, to) {
		log('doMoveAll: moving from ' + from.className + ' to ' + to.className);
		try {
			for ( var current = 0; current < from.options.length; current++) {
				to.options[to.length] = new Option(from.options[current].text,
						from.options[current].value);
				from.options[current--] = null; // Lose the instance in moveFrom
			}
		} catch (ex) {
			log(ex.message);
		}
		log('doMoveAll end');
	};
	
	var sortOptions = function(a,b){
		if(!a.text && !b.text){
			return 0;
		}
		else if(a.text && !b.text){
			return -1;
		}
		else if(!a.text && b.text){
			return 1;
		}
		else if(a.text === b.text){
			return 0;
		}
		var aLen = a.text.length;
		var bLen = b.text.length;
		if(aLen >= bLen){
			for(var i = 0;i < bLen;i++){
				if(a.text.charAt(i) > b.text.charAt(i)){
					return 1;
				}
				else if(a.text.charAt(i) < b.text.charAt(i)){
					return -1;
				}
			}
			if(aLen > bLen){
				return 1;
			}
			else {
				return -1;
			}
		}
		else {
			for(var i = 0;i < aLen;i++){
				if(a.text.charAt(i) > b.text.charAt(i)){
					return 1;
				}
				else if(a.text.charAt(i) < b.text.charAt(i)){
					return -1;
				}
			}
			if(aLen > bLen){
				return 1;
			}
			else {
				return -1;
			}				
		}
	};
	
	var populateHidden = function(hidden,options){
		if(hidden){
			hidden.value = '';
			for(var i = 0;i<options.length;i++){
				hidden.value += options[i].value + ",";
			}
		}
	};

	/**
	 * 
	 */
	var sort = function(select) {
		log('sort');
		var options = new Array();
			for(var cnt = select.options.length;--cnt >=0;){
				options.push(new Option(select.options[cnt].text,select.options[cnt].value));
				select.options[cnt] = null;
		}
		options.sort(sortOptions);
		log('sort end');
		for(cnt = 0;cnt < options.length;cnt++){
			select.options[cnt] = options[cnt];
		}
	};

	/**
	 * 
	 */
	var addItems = function(e) {
		log('addItems');
		var t = getTarget(e);
		var c = findContainer(t);
		var moveFrom = $('.AccumulatorFromChoices', c).get(0);
		var moveTo = $('.AccumulatorToChoices', c).get(0);
		var moveFound = doMoveSelected(moveFrom, moveTo);
		var hidden = $('input[type=hidden]',c).get(0);
		if (moveFound) {
			sort(moveTo);
			populateHidden(hidden,moveTo.options);
		}

	};

	/**
	 * 
	 */
	var removeItems = function(e) {
		log('removeItems');
		var t = getTarget(e);
		var c = findContainer(t);
		var moveFrom = $('.AccumulatorFromChoices', c).get(0);
		var moveTo = $('.AccumulatorToChoices', c).get(0);
		var moveFound = doMoveSelected(moveTo, moveFrom);
		var hidden = $('input[type=hidden]',c).get(0);
		if (moveFound) {
			sort(moveFrom);
			populateHidden(hidden,moveTo.options);
		}
	};

	/**
	 * 
	 */
	var addAll = function(e) {
		log('addAll');
		var t = getTarget(e);
		var c = findContainer(t);
		var moveFrom = $('.AccumulatorFromChoices', c).get(0);
		var moveTo = $('.AccumulatorToChoices', c).get(0);
		var hidden = $('input[type=hidden]',c).get(0);
		doMoveAll(moveFrom, moveTo);
		sort(moveTo);
		populateHidden(hidden,moveTo.options);

	};

	/**
	 * 
	 */
	var removeAll = function(e) {
		log('removeAll');
		var t = getTarget(e);
		var c = findContainer(t);
		var moveFrom = $('.AccumulatorFromChoices', c).get(0);
		var moveTo = $('.AccumulatorToChoices', c).get(0);
		var hidden = $('input[type=hidden]',c).get(0);
		doMoveAll(moveTo, moveFrom);
		sort(moveFrom);
		hidden.value = '';
	};
	
	

	var init = function() {
		$('.AccumulatorContainer').each(function(idx,c){
			var from = $('.AccumulatorFromChoices', c).get(0);
			sort(from);
			
			var to = $('.AccumulatorToChoices', c).get(0);
			var hidden = $('input[type=hidden]',c).get(0);
			populateHidden(hidden,to.options);
			
			var nbsp = '&#160;';
			var img = "<img width='1' height='1' />";

			var alb = document.createElement('div');
			alb.className = 'AccumulatorLftBrdr';
			alb.innerHTML = img;
			c.insertBefore(alb, c.firstChild);

			var aur = document.createElement('div');
			aur.className = 'AccumulatorUR';
			aur.innerHTML = img;
			c.insertBefore(aur, c.firstChild);

			var atb = document.createElement('div');
			atb.className = 'AccumulatorTopBrdr';
			atb.innerHTML = img;
			c.insertBefore(atb, c.firstChild);

			var aul = document.createElement('div');
			aul.className = 'AccumulatorUL';
			aul.innerHTML = img;
			c.insertBefore(aul, c.firstChild);

			var arb = document.createElement('div');
			arb.className = 'AccumulatorRightBrdr';
			arb.innerHTML = nbsp;
			c.appendChild(arb);

			var all = document.createElement('div');
			all.className = 'AccumulatorLL';
			all.innerHTML = nbsp;
			c.appendChild(all);

			var abb = document.createElement('div');
			abb.className = 'AccumulatorBtmBrdr';
			abb.innerHTML = nbsp;
			c.appendChild(abb);

			var alr = document.createElement('div');
			alr.className = 'AccumulatorLR';
			alr.innerHTML = nbsp;
			c.appendChild(alr);

			
			
			$('button', c).each(function(idx,anchor){
				if (anchor.className.indexOf('AccumulatorAddAll') != -1) {
					log('attaching handler to addAll');
					attachEvent(anchor, 'click', addAll);
				} else if (anchor.className.indexOf('AccumulatorAdd') != -1) {
					log('attaching handler to add');
					attachEvent(anchor, 'click', addItems);
				} else if (anchor.className
						.indexOf('AccumulatorRemoveAll') != -1) {
					log('attaching handler to removeAll');
					attachEvent(anchor, 'click', removeAll);
				} else if (anchor.className
						.indexOf('AccumulatorRemove') != -1) {
					log('attaching handler to remove');
					attachEvent(anchor, 'click', removeItems);
				}
			});
		});
	};

	NK.Accumulator = {
		init:init
	}
	
	$(window).load(function(){NK.Accumulator.init();});
	
})();
