/*jslint browser: true, sloppy: true, white: true, plusplus: true, maxerr: 50, indent: 8 */

(function(global)
{
	var JSON_PATH = "assets/json/sitedata.json",
	CONTENT_IMAGE_PATH = "assets/images/content/",
	siteData,
	commonElements = 
	{
		"noscript": global.document.getElementById("noscript"),
		"contentBoxCenter": global.document.getElementById("content_box_center"),
		"contentBoxRight": global.document.getElementById("content_box_right"),
		"promoImage": global.document.getElementById("promo_image"),
		"primaryNav": global.document.getElementById("primary_nav"),
		"secondaryNav": global.document.getElementById("secondary_nav"),
		"secondaryNavBody": global.document.getElementById("secondary_nav_body")
	},
	hashes = ["agriculture", "construction", "custom_packaging", "geotechnical", "insulation"],
	promoTimer,
	currentPromo = 0;

	// DOM UTILITIES

	function isElementNode (node)
	{
		return !!(node.nodeType && node.nodeType === 1);
	}

	function pushChars (chars, list)
	{
		if (chars.length)
		{
			list.push(chars.toString());
			return list;
		}
		return null;
	}

	function generateClassList (node)
	{
		var classData,
		i = 0, limit, list = [],
		chars = "", charFound;
		if (isElementNode(node))
		{
			classData = node.className;
			limit = classData.length;
			while (i < limit)
			{
				charFound = (/\S/).test(classData.charAt(i));
				if (charFound)
				{
					chars += classData.charAt(i);		
				}else if (!charFound)
				{
					pushChars(chars, list);
					chars = "";
				}
				++i;
			}
			pushChars(chars, list);
			return list;
		}
		return null;
	}

	function generateClassListHash (node)
	{
		var classes, hash = {},
		i = 0, limit;
		if (isElementNode(node))
		{
			classes = generateClassList(node);
			limit = classes.length;
			for (i;i<limit;i++)
			{
				hash[classes[i]] = classes[i];
			}
			return hash;
		}
		return null;
	}

	function hasClass (find, node)
	{
		var classes;
		if ((/\s/).test(find))
		{
			throw new Error("hasClass: Class to find cannot contain whitespace");
		}
		if (isElementNode(node))
		{
			classes = generateClassListHash(node);
			return !!classes[find];
		}
		return null;
	}

	function addClass (add, node)
	{
		var classes;
		if ((/\s/).test(add))
		{
			throw new Error("addClass: Class to add cannot contain whitespace");
		}
		if (isElementNode(node))
		{
			classes = node.className;
			if (!hasClass(add, node))
			{
				classes = classes.split(/\s/);
				classes.push(add);
				node.className = classes.join(" ");
			}
		}
	}

	function removeClass (remove, node)
	{
		var classes,  i = 0, limit,
		output = [];
		if ((/\s/).test(remove))
		{
			throw new Error("removeClass: Class to remove cannot contain whitespace");
		}
		if (isElementNode(node))
		{
			classes = node.className.split(/\s/);
			limit = classes.length;
			for (i;i<limit;i++)
			{
				if (classes[i] !== remove)
				{
					output.push(classes[i]);
				}
			}
			node.className = output.join(" ");
		}
	}

	function getChildren (node)
	{
		var nodes, i,
		temp = [], limit;
		if (isElementNode(node))
		{
			nodes = node.childNodes;
			limit = nodes.length;
			for (i = 0;i<limit;i++)
			{
				if (node.nodeType === 1)
				{
					temp.push(nodes[i]);
				}
			}
			return temp;
		}
		return null;
	}

	function clearChildNodes (node)
	{
		if (node.nodeType)
		{
			while (node.firstChild)
			{
				node.removeChild(node.firstChild);
			}	
		}
	}

	function recurseChildNodes (node, data, callback)
	{
		var i = 0, output = [],
		nodes, limit, result;
		if (isElementNode(node))
		{
			nodes = node.childNodes;
			limit = nodes.length;
			for (i;i<limit;i++)
			{
				result = callback (nodes[i], data);
				if (result)
				{
					output.push(result);
				}
				if (nodes[i].childNodes)
				{
					output = output.concat(recurseChildNodes(nodes[i],
					data, callback));
				}
			}
			return output;
		}
		return null;
	}

	function DataManager ()
	{
		var instance = {},
		stored = {};
		instance.setData = function (data)
		{
			stored = data;
		};
		instance.getData = function ()
		{
			return stored;
		};
		return instance;
	}

	function CellImage (src, alt, title)
	{
		var instance = global.document.createElement("img");
		addClass("secondary_nav_image", instance);
		instance.onerror = function() 
		{
			instance.src = "assets/images/secondary_nav/dummy.jpg";
			instance.onerror = null;
		};
		instance.onload = function(){};
		instance.src = src;
		instance.alt = alt || "cell image";
		instance.title = title || "cell image";
		return instance;
	}

	function ContentImage (src, alt, title)
	{
		var instance = global.document.createElement("img");
		addClass("content_box_image", instance);
		instance.onerror = function() 
		{
			instance.src = "assets/images/content/agriculture.jpg";
			instance.onerror = null;
		};
		instance.onload = function(){};
		instance.src = src;
		instance.alt = alt || "content image";
		instance.title = title || "content image";
		return instance;
	}

	function removeStylesheet ()
	{
		var noscript = commonElements.noscript;
		noscript.parentNode.removeChild(noscript);
	}

	function initSiteData ()
	{
		siteData = new DataManager();
	}

	function addSelectedNavClass (node, data)
	{
		if (isElementNode(node))
		{
			if (node.href && node.href.split("#")[1] === data.hash)
			{
				addClass("primary_nav_selected", node);
				return node;
			}
		}
		return null;
	}

	function selectPrimaryNavItem (hash)
	{
		recurseChildNodes(commonElements.primaryNav,
		{"hash": hash}, addSelectedNavClass);
	}

	function populateCenterContent (hash)
	{
		var contentBox = commonElements.contentBoxCenter,
		imagePath = CONTENT_IMAGE_PATH + hash + ".jpg",
		firstLetterOfWord = /\b([a-z])/g,
		contentImage, getFirstLetter, altText = hash;
		firstLetterOfWord.lastIndex = 0;
		altText = altText.replace(/_/g, " ");
		do
		{
			getFirstLetter = firstLetterOfWord.exec(altText);
			if (getFirstLetter)
			{
				altText = altText.replace(getFirstLetter[1],
				getFirstLetter[1].toUpperCase());
			}
		}while(getFirstLetter);
		contentImage = new ContentImage(imagePath, altText, altText);
		clearChildNodes(contentBox);
		contentBox.appendChild(contentImage);	
	}

	function createImageCell (row, index, data)
	{
		var cell = row.insertCell(index),
		cellImage = new CellImage(data.image, data.title, data.title);
		addClass("secondary_nav_item", cell);
		cell.appendChild(cellImage);
		return cell;
	}

	function createTextCell (row, index, data)
	{
		var cell = row.insertCell(index),
		cellAnchor = global.document.createElement("a"),
		cellText = global.document.createTextNode(data.title);
		cellAnchor.href = data.link;
		cellAnchor.title = cellText.data;
		addClass("secondary_nav_link", cellAnchor);
		addClass("basic_link", cellAnchor);
		addClass("title_text", cellAnchor);
		cellAnchor.appendChild(cellText);
		cell.appendChild(cellAnchor);
		return cell;
	}

	function populateItems (items, imagesRow, textRow)
	{
		var i = 0, limit = items.length,
		imageCell, textCell;
		for(i;i<limit;i++)
		{
			if (!items[i].title)
			{
				throw new Error("populateItems: Navigation cell requires a title.");
			}
			if (!items[i].link)
			{
				throw new Error("populateItems: Navigation cell requires a link path.");
			}
			if (!items[i].image)
			{
				throw new Error("populateItems: Navigation cell requires an image path");
			}
			imageCell = createImageCell(imagesRow, i, items[i]);
			textCell = createTextCell(textRow, i, items[i]);
			imageCell = null;
			textCell = null;
		}
	}

	function populateSecondaryNav (items)
	{
		var navBody = commonElements.secondaryNavBody,
		imagesRow, textRow;
		clearChildNodes(navBody);
		imagesRow = navBody.insertRow(0);
		textRow = navBody.insertRow(1);
		imagesRow.id = "secondary_nav_images";
		textRow.id = "secondary_nav_text";
		populateItems(items, imagesRow, textRow);
	}

	function checkHash (overrideHash)
	{
		var hash, data, description, items;
		if (overrideHash)
		{
			if (/#/.test(overrideHash))
			{
				overrideHash = overrideHash.replace("#", "");
			}
			hash = overrideHash;
		}else if (!overrideHash && global.location.hash)
		{
			hash = global.location.hash.replace("#", "");
		}else if (!overrideHash && !global.location.hash)
		{
			hash = "agriculture";
		}
		data = siteData.getData().categories[hash] || {};
		description = data.description || "";
		items = data.items || [];
		selectPrimaryNavItem(hash);
		populateCenterContent(hash);
		populateSecondaryNav(items);
	}

	function clearSelectedNavClasses (node)
	{
		if (isElementNode(node))
		{
			if (hasClass("primary_nav_selected", node))
			{
				removeClass("primary_nav_selected", node);
			}
		}
		return null;
	}

	function primaryNavClicked (href)
	{
		var primaryNav = commonElements.primaryNav,
		hash;
		recurseChildNodes(primaryNav, {}, clearSelectedNavClasses);
		hash = href.split("#")[1];
		checkHash(hash);
	}

	function delegateClickTarget (evt)
	{
		var target;
		if (evt)
		{
			target = evt.target;
		}else if (!evt)
		{
			target = global.event.srcElement;
		}
		if(hasClass ("primary_nav_link", target))
		{
			primaryNavClicked(target.href);
		}else if (hasClass("primary_nav_item", target))
		{
			primaryNavClicked(getChildren(target)[0].href);
		}
	}

	function addListeners ()
	{
		global.document.documentElement.onclick = delegateClickTarget;
	}

	function switchPromo (data)
	{
		var image = commonElements.promoImage;
		if (!data.src)
		{
			throw new Error("switchPromo: Src attribute required");
		}
		if (!data.title)
		{
			throw new Error("switchPromo: Title attribute required");
		}
		image.alt = data.title;
		image.src = data.src;
		image.title = data.title;
		
	}

	function addPromoTimer (time)
	{
		var images = siteData.getData().promos,
		nextIndex = (++currentPromo) % images.length,
		nextImage = images[nextIndex];
		global.clearTimeout(promoTimer);
		switchPromo(nextImage);
		promoTimer = global.setTimeout(function (){ addPromoTimer(time); }, time);
	}
	
	function initSiteUI ()
	{
		var blacklist = {"null": true, "undefined": true},
		rand = Math.floor(Math.random() * hashes.length),
		hash,
		promoTime = 20000;
		if (!blacklist[global.location.hash])
		{
			hash = hashes[rand];
			global.location.hash = hash;
		}
		checkHash(hash);
		addListeners();
		promoTimer = global.setTimeout(function (){ addPromoTimer(promoTime); }, promoTime);
	}

	function jsonLoading (request)
	{
		var json;
		if (request)
		{
			if (request.readyState === 4)
			{
				if (request.status === 200)
				{
					json = request.responseText;
					json = JSON.parse(json);
					siteData.setData(json);
					initSiteUI();
					request.onreadystatechange = function () {};
					request = null;
					json = null;
				}
			}
		}else if (!request)
		{
			throw new Error("jsonLoading: function requires XHR instance");
		}
	}

	function loadJSON (path)
	{
		var xhr;
		if (global.XMLHttpRequest)
		{
			xhr = new global.XMLHttpRequest();
		}else if (global.ActiveXObject)
		{
			xhr = new global.ActiveXObject("Microsoft.XMLHTTP");
		}
		xhr.open("GET", path, true);
		xhr.setRequestHeader("Content-Type",  "application/json;charset=UTF-8");
		xhr.onreadystatechange = function ()
		{
			jsonLoading(xhr);	
		};
		xhr.send();
	}

	removeStylesheet();
	initSiteData();
	loadJSON(JSON_PATH);
}(this));

