/// Package: CDON.ui
Incordia.Packages.create("CDON.ui");

/// Class: Scissors
///  Splits up text in certain elements, to allow for a short/long text toggle.
CDON.ui.Scissors = Incordia.Class.extend({
	args: null,
	textNode: 3,
	toggler: null,
	shortText: null,
	longText: null,
	
	
	constructor: function(args)
	{
		this.args = Incordia.merge(CDON.ui.Scissors.defaults, args);
	},
	
	load: function()
	{
		var elems = $A(document.getElementsByTagName(this.args.tag));
		this.toggler = new Array();
		this.longText = new Array();
		this.shortText = new Array();
		var re = new RegExp("(^|\\s)" + (this.args.className) + "(\\s|$)");
		for(var i=0, tag; tag = elems[i]; ++i)
		{
			if(re.test(tag.className))
			{
				var flashes = tag.getElementsByTagName("embed");
				for (var j = 0; j < flashes.length; j++)
				{
					var flash = flashes[j];
					if (flash.outerHTML) flash.outerHTML = "";
				}
				
				this.register(tag);
			}
		}
	},
	
	register: function(realEm)
	{
		var em = realEm.cloneNode(true);
		em.className = this.args.shortClassName;
		var list = [];
		var complete = [];
		var length = this._generate(em, list, complete);
		var text = this._trim(complete.join(""));
		if((this.args.maxLength + this.args.mercyLength) >= length) return;
		
		var nextCutOff = text.indexOf(" ", this.args.maxLength);
		var prevCutOff = text.lastIndexOf(" ", this.args.maxLength);
		// console.log(text.substring(0, prevCutOff) + "[P]" + text.substr(prevCutOff, this.args.maxLength - prevCutOff) + "[$]" + text.substr(this.args.maxLength, nextCutOff - this.args.maxLength) + "[N]" + text.substring(nextCutOff));
		
		var nextDistance = nextCutOff - this.args.maxLength;
		var prevDistance = this.args.maxLength - prevCutOff;
		
		var useNext = nextDistance == -1
				    ? (prevDistance == -1 ? null : prevDistance)
				    : (prevDistance == -1 || prevCutOff <= 0 ? true : nextDistance < prevDistance);
		if(useNext == null) return;
		
		
		var cutOff = (useNext ? nextCutOff : prevCutOff) + 1;
		if((cutOff + this.args.mercyLength) >= length) return;
		if(cutOff == length || cutOff == 0) return;
		
		cutOff--; // clip the trailing space.
		for(var i=0, item; item = list[i]; ++i)
		{
			if(item.offset + item.length < cutOff) continue;
			var diff = (item.offset + item.length) - cutOff;
			this._performMayhem(em, item.node, item.length - diff);
			
			var trimmed = this._trim(item.node.nodeValue);
			item.node.nodeValue = trimmed.substring(0, trimmed.length - diff);
			this._addFooter(em);
			
			break;
		}
		this._finish(realEm, em);
	},
	
	
	
	
	
	
	_finish: function(longText, shortText)
	{
		//this.longText = longText;
		//this.shortText = shortText;
		
		var wrapper = $make("div", {className: this.args.wrapperClassName});
		wrapper.setAttribute("class", this.args.wrapperClassName);
		
		var target = longText.parentNode;
		var nextNode = longText.nextSibling;

		target.removeChild(longText);
		wrapper.appendChild(longText);
		wrapper.appendChild(shortText);
		
		var toggler = $make("div");
		this.toggler[this.toggler.length] = toggler;
		this.longText[this.longText.length] = longText;
		this.shortText[this.shortText.length] = shortText;
		var pos = this.toggler.length-1;
		addEvent(toggler, "click", (function() { this._toggle(pos); }).bind(this));
		this.counter++;
		toggler.innerHTML = this.args.toComplete;
		wrapper.appendChild(toggler);
		
		target.insertBefore(wrapper, nextNode);
		this._toggle(pos);
	},
	
	_toggle: function(pos)
	{
		if (pos!=undefined)
		{
			var showingLong = this.longText[pos].style.display != "none";
			this.toggler[pos].innerHTML = showingLong?this.args.toComplete:this.args.toCut;
			this.toggler[pos].className = showingLong?this.args.togglerClassNameOff:this.args.togglerClassNameOn;
			this.longText[pos].style.display  = showingLong?"none":"";
			this.shortText[pos].style.display = showingLong?"":"none";
		}
	},
	
	
	
	
	
	
	_generate: function(em, list, complete, current)
	{
		if(!current) current = 0;
		if(!complete) complete = [];
		
		for(var i=0, n; n = em.childNodes[i]; ++i)
		{
			if(n.nodeType == this.textNode)
			{
				var text = this._trim(n.nodeValue);
				var length = text.length;
				complete.push(text);
				list.push({offset: current, length: length, node:  n});
				current += length;
			}
			else current = this._generate(n, list, complete, current);
		};
		return current;
	},
	
	_performMayhem: function(base, seekNode, cutOff)
	{
		var mayhem = false;
		for(var i=0, n; n = base.childNodes[i]; ++i)
		{
			if(!mayhem)
			{
				if(n == seekNode)
					mayhem = true;
				else
				{
					var result = this._performMayhem(n, seekNode, cutOff);
					mayhem = result.isMayhem;
				}
				continue;
			}
			n.parentNode.removeChild(n);
			--i;
		}
		return { isMayhem: mayhem }
	},
	
	_trim: function(s)
	{
		return s.replace(/\s+/g," ");
	},
	
	
	_addFooter: function(em)
	{
		var footer = $make("span")
		footer.innerHTML = this.args.footerText;
		
		if(em.lastChild.nodeType!=this.textNode)
			 { em.lastChild.appendChild(footer) }
		else { em.appendChild(footer); }
	},
	
	global:
	{
		defaults:
		{
			tag: "div",
			className: "text-to-cut",
			shortClassName: "shortened-text",
			wrapperClassName: "scissor-wrap",
			togglerClassNameOn: "scissor-toggler scissor-toggler-on",
			togglerClassNameOff: "scissor-toggler scissor-toggler-off",
			
			
			footerText: "&hellip;",
			toComplete: "Visa hela texten",
			toCut: "Visa bara lite grand",
			
			maxLength: 10,
			mercyLength: 5
		}
	}
});
