var RELLINT = function() {
	
	var cssPath		= 'http://tools.microformatic.com/rel-lint/rel-lint.css';
	var idPrefix	= 'rel-lint-';
	var prefixCount = 0;
	var foundLinks	= [];
	var prevHighlight;
	
	var XFN			= ['contact', 'acquaintance', 'friend', 'met', 'co-worker', 'colleague', 'co-resident', 'neighbor', 'child', 'parent', 'sibling', 'spouse', 'kin', 'muse', 'crush', 'date', 'sweetheart', 'me'];	
	var W3C			= ['alternate', 'stylesheet', 'start', 'next', 'prev', 'contents', 'index', 'glossary', 'copyright', 'chapter', 'section', 'subsection', 'appendix', 'help', 'bookmark'];
	var MISC		= ['home', 'license'];
	var VoteLinks	= ['vote-for', 'vote-against', 'vote-abstain'];
	
	var relValues	= (XFN + ',' + MISC + ',' + W3C).split(',');
	
	var me;
	
	var findLinks = function() {
		var i, l;
		var links	= document.getElementsByTagName('a');
		var links_with_rel	= [];
		var oTmp;
		
		for (i=0, l=links.length; i<l; i++){
			if (links[i].hasAttribute('rel')){
				oTmp		= {};
				oTmp.rel	= links[i].getAttribute('rel'); 
				oTmp.href	= links[i].getAttribute('href'); 
				oTmp.y		= links[i].offsetTop;
				
				if (links[i].textContent){
					oTmp.text	= links[i].textContent;
				}else{
					oTmp.text	= links[i].firstChild.nodeValue;
				}

				if (links[i].hasAttribute('id')){
					oTmp.id	= links[i].getAttribute('id');
				}else{
					oTmp.id 	= generateId();
					links[i].id	= oTmp.id;
				}
				links_with_rel.push(oTmp); 
			}
		}
		
		foundLinks	= links_with_rel;
	}
	
	
	var checkKnownRels = function() {
		var links	= foundLinks;
		var i, l, link, j, k;

		for (i=0, l=links.length; i<l; i++){
			link 		= links[i];
			link.rels	= [];
			
			for (j=0, k=relValues.length; j<k; j++){
				var pattern = '' + relValues[j] + '';
				var regexp	= new RegExp(pattern, 'i');
				

				if (regexp.test(link.rel)){
				
					link.rels = link.rel.split(' ');
					verifyRels(link);
					break;
				}else{
					
				}
				regexp = null;
			}	
		}
	}
	
	
	var verifyRels = function(link) {
		var found, i, l, j, k;
		
		link.suspicious	= [];
		
		for (i=0, l=link.rels.length; i<l; i++){
			found = false;
			for (j=0, k=relValues.length; j<k; j++){
				if (relValues[j] == link.rels[i]){
					found = true;
				}
			}
			if (!found && link.rels[i]!='tag'){
				link.suspicious.push(link.rels[i]);
			}
		}
		
		//check for bad VoteLinks
		link.votelink = false;
		
		for (i=0, l=link.rels.length; i<l; i++){
			for (j=0, k=VoteLinks.length; j<k; j++){
				if (VoteLinks[j] == link.rels[i]){
					link.votelink = true;
					break;
				}
			}
		}
		
	}
	
	
	var checkTags	= function(){
		var links	= foundLinks;
		var i, l, link, tag;

		for (i=0, l=links.length; i<l; i++){
			var link	= links[i];
			var pattern = 'tag';
			var regexp	= new RegExp(pattern, 'i');
			
			if (regexp.test(link.rel)){
				tag		= link.href.replace(/(.*)\?(.*)$/i, '$1').split('/').pop().split('?').reverse().pop().split('#').reverse().pop();

				if (tag){
					link.tag	= tag;
				}
			}
			regexp = null;	
		}
	}
	
	
	var generateId	= function(){
		prefixCount++;
		return idPrefix + '' + prefixCount;
	}
	
	
	var displayResults	= function(){
		var i, j;
		var link, errorItem, errorTitle, errorDesc, errorText, errorLink, errorLinkText;
		
		var container 		= document.createElement('div');
		container.setAttribute('id', 'rel-lint-container');
		
		var heading			= document.createElement('h1');
		var headingText		= document.createTextNode('rel-lint results');
		heading.appendChild(headingText);
		
		container.appendChild(heading);
		
		
		var hint			= document.createElement('p');
		hint.setAttribute('class', 'hint');
		var hintText		= document.createTextNode('Valid XFN values are: ' + XFN.join(', '));
		hint.appendChild(hintText);
		
		container.appendChild(hint);
		
		var tabA			= document.createElement('dl');
		var tabB			= document.createElement('dl');
		
		tabA.id				= 'rel-lint-tab-id-A';
		tabB.id				= 'rel-lint-tab-id-B';
		
		// suspicious!
		for (i=0, l=foundLinks.length; i<l; i++){
			link	= foundLinks[i];
			
			if (link.suspicious && link.suspicious.length>0){
				buildReportLine(tabA, link, 'Suspicious value:', '', link.suspicious.join(', '));
			}
		}
		
		// bad VoteLinks
		for (i=0, l=foundLinks.length; i<l; i++){
			link	= foundLinks[i];
			
			if (link.votelink){
				buildReportLine(tabA, link, 'Bad VoteLink:', '', 'should use rev attribute');
			}
		}
		
		// non-sus
		for (i=0, l=foundLinks.length; i<l; i++){
			link	= foundLinks[i];
			if (link.rels && link.rels.length>0){
				if (link.suspicious && link.suspicious.length>0){
				}else{
					buildReportLine(tabA, link, 'Good values:', 'good', link.rels.join(', '));
				}
			}
		}
		
		// rel-tags
		for (i=0, l=foundLinks.length; i<l; i++){
			link	= foundLinks[i];
			if (link.tag){
				buildReportLine(tabB, link, 'Tag:', 'tag', link.tag);
			}
		}
		
		if (tabA.childNodes.length > 0 || tabB.childNodes.length > 0){
			var tabs	= document.createElement('div');
			tabs.id		= 'rel-lint-tabs';
			if (tabA.childNodes.length > 0) tabs.appendChild(tabA);			
			if (tabB.childNodes.length > 0) tabs.appendChild(tabB);

			container.appendChild(tabs);			

			var btns	= document.createElement('div');
			btns.id		= 'rel-lint-tab-btns';
			
			var tabAbtn		= document.createElement('a');
			tabAbtn.href	= '#';
			tabAbtn.className	= 'selected';
			tabAbtn.appendChild(document.createTextNode('Main'));
			tabAbtn.onclick	= function(){
				me.switchTabs('A')
				this.className = 'selected';
			};
			btns.appendChild(tabAbtn);
			
			btns.appendChild(document.createTextNode(' '));
			
			var tabBbtn		= document.createElement('a');
			tabBbtn.href	= '#';
			tabBbtn.appendChild(document.createTextNode('rel-tag'));
			
			tabBbtn.onclick	= function(){
				me.switchTabs('B')
				this.className = 'selected';
			};
			btns.appendChild(tabBbtn);

			container.appendChild(btns);
			
		}else{
			var allOK	= document.createTextNode('Sorry, no recognised rel values were found');
			container.appendChild(allOK);
		}
		
		
		var footer		= document.createElement('p');
		footer.setAttribute('class', 'footer');
		
		var footerText	= document.createTextNode('This is like way beta. Feedback: comments@allinthehead.com.');
		footer.appendChild(footerText);
		
		container.appendChild(footer);
		
		var closeLink		= document.createElement('a');
		closeLink.id		= 'rel-lint-close';
		closeLink.href		= window.location.href;
		closeLink.onclick	= closeAndClean;
		
		container.appendChild(closeLink);
		
		document.getElementsByTagName('body')[0].appendChild(container);
	}
	
	var buildReportLine	= function(list, link, label, className, value){
		var rItem, rTitle, rDesc, rLink, rLinkText;
		
		rItem	= document.createElement('dt');
		rTitle	= document.createTextNode(label);
		rItem.className	= className;
	
		rItem.appendChild(rTitle);
	
		rDesc	= document.createElement('dd');
		rText	= document.createTextNode(value + ' on ');
		rDesc.appendChild(rText);
		rDesc.className	= className;
	
		rLink	= document.createElement('a');
		rLink.setAttribute('href', '#' + link.id);
		rLink.orig	= link;
		
		rLink.onclick	= function(){
			showLink(this.orig);
			return false;
		};
		
	
		rLinkText	= document.createTextNode(constrain(link.text, 40));
		rLink.appendChild(rLinkText);
	
		rDesc.appendChild(rLink);
	
	
		list.appendChild(rItem);
		list.appendChild(rDesc);
		
		
	}
	
	var addCSS	= function() {
		var stylesheet	= document.createElement('link');
		stylesheet.setAttribute('rel', 'stylesheet');
		stylesheet.setAttribute('type', 'text/css');
		stylesheet.setAttribute('href', cssPath);
		stylesheet.id	 = 'rel-lint-css';
		document.getElementsByTagName('head')[0].appendChild(stylesheet);
	}
	
	
	var closeAndClean	= function(ev) {
		if (ev.stopPropagation) {ev.stopPropagation();} else {ev.cancelBubble = true;}
		if (ev.preventDefault) {ev.preventDefault();} else {ev.returnValue = false;}
		
		var cont	= document.getElementById('rel-lint-container');
		cont.parentNode.removeChild(cont);
		
		var styles	= document.getElementById('rel-lint-css');
		styles.parentNode.removeChild(styles);
		
		var head 	= document.getElementsByTagName('head')[0];
		var scripts	= head.getElementsByTagName('script');
		head.removeChild(scripts[0]);

	}
	
	var showLink	= function(o) {
		window.scrollTo(0, o.y);
		var link	= document.getElementById(o.id);
		
		if (prevHighlight){
			prevHighlight.style.border 	= 'none';
		}
		
		prevHighlight				= link;
		link.style.border 			= '2px solid red';
		
		
	}
	
	var constrain	= function(str, n){ 
		if(str && str.length > n){
			var s = str.substr(0, n);
			var words = s.split(' '); 
			words[words.length-1] = '';
			str = words.join(' ');
			str = str.substr(0, str.length-1) + '... ';
		}
		return str;
	}
	
	return {
		
		init : function() {

			me	= this;
			
			findLinks();
			checkTags();
			checkKnownRels();
			addCSS();
			displayResults();
		},
		
		switchTabs : function(tab) {
			var tabs	= document.getElementById('rel-lint-tabs').getElementsByTagName('dl');
			var i, l;
			
			for (i=0, l=tabs.length; i<l; i++){
				if (tabs[i].id == 'rel-lint-tab-id-' + tab){
					tabs[i].style.zIndex	= 100;
				}else{
					tabs[i].style.zIndex	= 98;
				}
			}
			
			var buttons	= document.getElementById('rel-lint-tab-btns').getElementsByTagName('a');
			
			for (i=0, l=buttons.length; i<l; i++){
				buttons[i].className = '';
			}
		}
		
		
	}
}();


RELLINT.init();