/*
 * Doc contains some short time saving methods
 */
function DocumentMachine()
{
	// The first element of the document.
	this.current = document.getElementsByTagName("body")[0];
	
	this.text_filter = {"prev": null, method: null};
	this.text_begin = {"text": "", "prev": null, method:null};
	this.text_end = {"text": "", "prev": null, method:null};
	
	this.marked_points = new Array();
	
	this.tag_filters = new Object();
};
	
	
// Changes the mode between: dig, sib, 
DocumentMachine.prototype.mode = function(mode_m) 
{
	this.mode_method = mode_m;
}

DocumentMachine.prototype.seek = function(id_str)
{
	return document.getElementById(id_str);
}

DocumentMachine.prototype.pushTagFilter = function(tagName, method)
{
	if(this.tag_filters[tagName])
	{
		this.tag_filters[tagName] = {prev: this.tag_filters[tagName], method: method};
	}
	else
	{
		this.tag_filters[tagName] = {prev: null, method: method};
	}
};

DocumentMachine.prototype.popTagFilter = function(tagName)
{
	if(this.tag_filters[tagName])
	{
		this.tag_filters[tagName] = this.tag_filters[tagName].prev;
	}
};
	
	
DocumentMachine.prototype.tag = function(tagName, className, id, attributes, html_code) 
{
	var el = document.createElement(tagName);
	
	if(className)
	{
		el.className = className;
	}
	
	if(id)
	{
		el.id = id;
	}
	
	if(attributes)
	{
		this.setAttributes(el, attributes);
	}
	
	if(html_code)
	{
		el.innerHTML = html_code;
	}
	
	this.current.appendChild(el);
	this.mode_method(el);
	
	if(this.tag_filters[tagName] && this.tag_filters[tagName].method)
	{
		this.tag_filters[tagName].method(el);
	}
	
	return el;
};

// Add attributes to a tag
DocumentMachine.prototype.setAttributes = function(el, attributes)
{
	for(var i in attributes)
	{
		el.setAttribute(i, attributes[i]);
		
		if(i == "style")
		{
			try {
				el.style.cssText = attributes[i]; // Because IE does not play nice.
			}
			catch(e)
			{
				// Just in case some browser has an issue with this non standard thing
			}
		}
	}
};
	
// Creates a text node and adds it to the current document.	
DocumentMachine.prototype.text = function(text)
{
	var text_node = null;
	var other_text_node = null;
	
	if(this.text_filter.method)
	{
		text = this.text_filter.method(text);
	}
	
	if(this.text_begin.text != "")
	{
		other_text_node = document.createTextNode(this.text_begin.text);
		this.current.appendChild(other_text_node);
	}
	
	if(this.text_begin.method)
	{
		this.text_begin.method();
	}
	
	text_node = document.createTextNode(text);
	this.current.appendChild(text_node);
	
	if(this.text_end.method)
	{
		this.text_end.method();
	}

	if(this.text_end.text != "")
	{
		other_text_node = document.createTextNode(this.text_end.text);
		this.current.appendChild(other_text_node);
	}
	
	return text_node;
};

DocumentMachine.prototype.pushTextEnding = function(text, method)
{
	this.text_end = {"text":text, "prev":this.text_end, "method":method};
};

DocumentMachine.prototype.pushTextBeginning = function(text, method)
{
	this.text_begin = {"text":text, "prev":this.text_begin, "method":method};
};

DocumentMachine.prototype.pushTextFilter = function(method)
{
	this.text_filter = {"prev": this.text_filter, "method":method};
}

DocumentMachine.prototype.popTextEnding = function()
{
	this.text_end = this.text_end.prev;
};

DocumentMachine.prototype.popTextBeginning = function()
{
	this.text_begin = this.text_begin.prev;
};

DocumentMachine.prototype.popTextFilter = function()
{
	this.text_filter = this.text_filter.prev;
};

// Used to ad an nbsp into elements that might not work without any content.
DocumentMachine.prototype.nbsp = function()
{
	this.text("\u00a0");
};
	
// sib - Short hand for sibling.
// Creates a tag on the same level.
DocumentMachine.prototype.sib = function() 
{
	// Nothing to do really.
};

// dig - enter the current created tag
DocumentMachine.prototype.dig = function(el)
{
	this.current = el;
};

// climb - exit the current tag
DocumentMachine.prototype.climb = function(i)
{
	if(!i)
	{
		 i = 1;
	}
	
	do
	{
		this.current = this.current.parentNode;
		i--;
	} while(i > 0);
};

// Add Event
DocumentMachine.prototype.setEvent = function(el, event_type, callback)
{
	if (window.addEventListener)
	{
		el.addEventListener(event_type, callback, false);
	}
	else if (window.attachEvent)
	{
		el.attachEvent("on"+event_type, callback);
	}
};

DocumentMachine.prototype.del = function(el)
{
	el.parentNode.removeChild(el);
};

DocumentMachine.prototype.htmlToText = function(html)
{
	var temp = document.createElement("span");
	temp.innerHTML = html;
	
	return temp.innerText || temp.textContent || (temp.childNodes.length > 0 && temp.childNodes[0].nodeValue) || "";
};

DocumentMachine.prototype.mark = function()
{
	this.marked_points.push(this.current);
};

DocumentMachine.prototype.jump = function()
{
	if(this.marked_points.length > 0)
	{
		this.dig(this.marked_points.pop());
	}
};

DocumentMachine.prototype.getStyle = function(el, prop)
{
	if(el != null)
	{
		// Note: check getComputedStyle first it is the standard and works
		// better in Opera (which supporst both)
		if (window.getComputedStyle)
		{
			return window.getComputedStyle(el, null)[prop];
		}
		else if(el.currentStyle)
		{
			return el.currentStyle[prop];
		}
		else
		{
			return el.style[prop];
		}
	}
	
	return null;
};

/**
 * These next few methods may be a case of feature envy.
 */

DocumentMachine.prototype.parseLinks = function(str)
{
	var sub_strings = this.whiteSpaceSplit(str);
	var protocal_part = new RegExp("[A-Za-z]+://", "i");
	var www_part = new RegExp("www\.", "i");
	var s = null;
	var result = "";
	
	for(var sub_string = 0; sub_string < sub_strings.length; sub_string++)
	{
		if(sub_string > 0)
		{
			result += " ";
		}
		
		s = sub_strings[sub_string];
		
		if(s.search(protocal_part) == 0)
		{
			result += "<a href=\"" + s + "\" rel=\"nofollow\" target=\"_blank\"><u>" + s + "</u></a>";
		}
		else if(s.search(www_part) == 0)
		{
			result += "<a href=\"http://" + s + "\" rel=\"nofollow\" target=\"_blank\"><u>" + s + "</u></a>";
		}
		else
		{
			result += s;
		}
	}
	
	return result;
};

DocumentMachine.prototype.truncateTaggedText = function(str, length_limit)
{
	var result = "";
	var tag_depth = 0;
	var x = 0;
	
	for(var i = 0; i < str.length; i++)
	{
		if(str.charAt(i) == '<') tag_depth++;
		else if(str.charAt(i) == '>') tag_depth--;
		
		if(tag_depth < 0) tag_depth = 0;
		
		if(tag_depth > 0) result += str.charAt(i);
		else if(x < length_limit)
		{
			result += str.charAt(i);
			x++;
		}
	}
	
	return result;
};

DocumentMachine.prototype.whiteSpaceSplit = function(str)
{
	var result = str.replace(/\s/g, " ");
	return result.split(" ");
};
