
var site = new Website();
var browser = new Browser();

var placeholderComment = "Enter your comment here.";



function Website () {

	var thisthis = this;

	this.menus = {
		"About"   : new DamnMenu('About'),
		"Explore" : new DamnMenu('Explore'),
		"Shop"    : new DamnMenu('Shop'),
		"Login"   : new DamnMenu('Login'),
		"Profile" : new DamnMenu('Profile')		
	};

	this.dom              = new WebsiteDOM();	
	this.queues           = [];
	this.menuButtons      = null;
	this.blackBack        = null;
	this.menusContainer   = null;
	this.commentsTextarea = null;
	
	this.regexp = {
		'trim' : /^\s+|\s+$/g,
		'tags' : /<[^>]+>/ig
	};
	


	this.toggleMenu = function (name) {
		var menu = this.menus[name];
		this.init();
		
		if (menu.open) {
			this.hideOpenMenus();
		}
		else {
			this.openMenu(name);
		}
	};


	this.openMenu = function (name) {
		var menu = this.menus[name];
		this.init();
		
		this.hideOpenMenus();
		this.menusContainer.style.display = 'block';	
		menu.show();
		this.fadeBackground();
	};
	
	
	this.hideOpenMenus = function () {
		this.init();
		
		if (site.blackBack.css.opacity > 0) {
			var queue = site.blackBack.setOpacity(0, 5, 10);
			queue.push(function () { site.blackBack.style.display = 'none'; });		
		}
		
		for (var menuName in this.menus) {
			this.menus[menuName].hide();
		}

		this.menusContainer.style.display = 'none';	
	};
	
	
	this.fadeBackground = function () {
		var width = browser.getInnerWidth() - 20;
		
		if (!this.blackBack.css.opacity || this.blackBack.css.opacity != 80) {
			this.blackBack.setOpacity(0);
		}
		this.blackBack.style.top = browser.getScrollTop() + "px";
		this.blackBack.style.marginLeft = "-" + (Math.floor(width)/2) + "px";
		this.blackBack.style.height = Math.min(browser.getInnerHeight()+500, browser.getScrollHeight()) + "px";
		this.blackBack.style.width = width + "px";		
		this.blackBack.style.display = 'block';

		this.blackBack.setOpacity(80, 5, 10);
	};

	
	this.clearPlaceholderComment = function () {
		this.init();
		if (trim(this.commentsTextarea.value) == placeholderComment) {
			this.commentsTextarea.value = '';
		}
	};
	
	
	this.addPlaceholderComment = function () {
		if (trim(this.commentsTextarea.value) == '') {
			this.commentsTextarea.value = placeholderComment;
		}
	};
	
	
	this.dontSubmitPlaceholderComment = function () {
		if (trim(this.commentsTextarea.value) == placeholderComment) {
			return FALSE;
		}
		else {
			return TRUE;
		}
	};
	

	this.setPreviousPageLinks = function (type, url) {
		var link = $('previousPageLink');
		var label = $('previousPageType');
		
		if (url) {		
			link.href = url;
			label.innerHTML = type;
			link.style.display = "block";			
		}
		else {
			link.style.display = "none";
		}
	};


	this.setNextPageLinks = function (type, url) {
		var link = $('nextPageLink');
		var label = $('nextPageType');
		
		if (url) {		
			link.href = url;
			label.innerHTML = type;
			link.style.display = "block";
		}
		else {
			link.style.display = "none";
		}
	};
	
	
	
	this.focusOn = function (field) {
		setTimeout(
			function () {
				field.focus();
				field.select();
			},
			10
		);
	};	
	
	
	this.quoteComment = function (username, commentBodyId) {
		var commentBody = $(commentBodyId).innerHTML;
		var queue = null;
		commentBody = commentBody.replace("</p>", "\n\n");
		commentBody = commentBody.replace(this.regexp.tags, "");
		
		this.clearPlaceholderComment();

		queue = browser.scrollTo(this.commentsTextarea.offsetTop, 40, 10);
		
		queue.push(
			function () {
				thisthis.commentsTextarea.value = trim(thisthis.commentsTextarea.value);
			
				if (thisthis.commentsTextarea.value) {
					thisthis.commentsTextarea.value += "\n\n";
				}
				thisthis.commentsTextarea.value+= '[quote]' + username + ' said: "' + trim(commentBody) + '"[/quote]' + "\n\n";
				thisthis.commentsTextarea.setCaretPosition(thisthis.commentsTextarea.value.length);
				thisthis.commentsTextarea.scrollTop = thisthis.commentsTextarea.scrollHeight;
				thisthis.commentsTextarea.focus();				
			}
		);
	};
	
	
	this.init = function () {
		if (!this.blackBack) {
			this.blackBack        = $('blackBack');
			this.menusContainer   = $('menus');
			this.commentsTextarea = $('commentsTextarea');
			
			window.onscroll = function () { thisthis.hideOpenMenus(); };
			window.onresize = function () { thisthis.hideOpenMenus(); };
		}
	};

};


function DamnMenu (name) {
	
	var thisthis = this;

	this.name            = name;
	this.buttonElementId = "menuButton" + name;
	this.menuElementId   = "menu" + name;
	this.buttonElement   = null;
	this.menuElement     = null;
	this.open            = false;
	
	
	this.show = function () {
		this.init();
		this.menuElement.style.display = 'block';
		this.buttonElement.css.addClass('menuButton' + name + 'Open');
		
		setTimeout(
			function () {
				thisthis.open = true;
			},
			10
		);
	};
	
	
	this.hide = function () {
		this.init();
		if (this.menuElement && this.open) {
			this.menuElement.style.display = 'none';
			this.buttonElement.css.removeClass('menuButton' + name + 'Open');
			this.open = false;
		}
	};
	

	this.init = function () {
		if (!this.buttonElement) {
			this.buttonElement = $(this.buttonElementId);
			this.menuElement   = $(this.menuElementId);
		}
	};

}



/* *** DOM FUNCS ************************************************************************** */


function WebsiteDOM () {
	
	this.body = null;
			
	
	this.get = function (id) {
		var e = null;
		if (id) {
			if (typeof(id) == "string") {
				e = this.enhance(document.getElementById(id));
			}
			else {
				e = this.enhance(id);
			}
		}
		return e;
	};
	
	
	this.getBody = function () {

		if (this.body == null) {
			var bodies = document.getElementsByTagName('BODY');
			
			if ( bodies != null && bodies.length > 0 ) {
				this.body = bodies[0];
				this.body.scroll = 'yes';
			}
			//this.body = this.enhance(document.body || document.documentElement);
		}
		return this.body;			
	};
	
	
	this.remove = function (e) {
		e = this.get(e);
		if (e && e.parentNode) {
			var result = e.parentNode.removeChild(e);
		}
		return e;
	};
	
	
	this.enhance = function (e) {
		
		if (e && e.tagName && ! e.css) {

			e.css = new CSS(e);
			
			
			e.create = function (tagName, className, id) {
				var newEl = document.createElement(tagName);
				newEl.setAttribute("id", id);
				newEl.className = className;
				return this.push(newEl);
			};
			
			
			e.createText = function (string) {
				var newEl = document.createTextNode(string);
				return this.push(newEl);
			};
			
			
			e.getParent = function () {
				return $(this.parent);
			};
			
			
			e.get = function (tagName, cssClass) {
				var els = this.getElementsByTagName(tagName);
				for (var i=0; i < els.length; i++) {
					if (els[i].className.indexOf(cssClass) > -1 || cssClass == null) {
						return $(els[i]);
					}
				}
			};
			
			
			e.getByClassName = function (name) {
				var kids = this.getChildren(true);
				var matches = [];
				
				for (var i=0; i < kids.length; i++) {
					if ($(kids[i]).css.hasClass(name)) {
						matches.push(kids[i]);
					}
				}
				return matches;
			};		
			
			//add ability to only fetch particular tag children
			e.getChildren = function (deep) {
				if (deep) {
					return $(this.getElementsByTagName("*"));
				}
				else {
					return $(this.childNodes);
				}
			};
			
			
			e.push = function (el) {
				this.appendChild(el);
				return $(el);
			};
			
			
			e.unshift = function (el) {
				if (this.childNodes.length > 0) {
					this.insertBefore(el, this.childNodes[0]);
				}
				else {
					this.push(el);
				}
				return $(el);
			};
			
			
			e.setOpacity = function (percent, steps, delay) {
				if (arguments.length == 1) {
					var visibility = 'visible';
					var ieFilter = '';

					if (percent == 0) {
						visibility = 'hidden';
					}
					else {
						if (browser.IE) {
							if (browser.ver >= 7) {
								ieFilter = "alpha(opacity=" + percent + ")";
							}
							else {
								ieFilter = "progid:DXImageTransform.Microsoft.BasicImage(opacity="+ (percent/100) +")";
							}
						}
						else {
							this.style.opacity = percent/100;	
						}
					}
					this.style.visibility = visibility;	
					this.style.filter = ieFilter;
					this.css.opacity = percent;
				}
				else {
					var current = this.css.opacity;
					var op = 0;
					var queue = new Queue(this.id + "opacity",  true);
					
					for (var i=0; i < steps; i++) {
						queue.push(
							function (el, opac) {
								el.setOpacity(opac);
							},
							[this, current + ((i+1) * ((percent - current)/steps))],
							delay
						);
					}
					queue.push(
						function (el) {
							el.setOpacity(percent);
						},
						this
					);
					return queue;
				}
			};
			
			
			if (e.tagName == "INPUT" || e.tagName == "TEXTAREA") {
				e.setCaretPosition = function (index) {
					if (this.setSelectionRange) {
						this.focus();
						this.setSelectionRange(index,index);
					}
					else if (this.createTextRange) {
						var range = this.createTextRange();
						range.collapse(true);
						range.moveEnd('character', index);
						range.moveStart('character', index);
						range.select();
					}		
				};
			}			
			
			
			e.onEvent = function (evName, action) {
				if (this.addEventListener) {
					this.addEventListener(evName, action, false);
				}
				else if (this.attachEvent) {
					this.attachEvent(evName, action);
				}
			};
			
		}
		
		return e;
	};
}


/* *** CSS FUNCS ************************************************************************** */

function CSS (e) {

	this.e          = e;
	this.opacity    = 100;
	this.propRegExp = /-(.)/g;
	
	
	this.get = function (p, returnInt) {
		var val;
		var currentStyle = eval("this.e.currentStyle");
		
		if (browser.IE) {
			if (eval("this.e.currentStyle")) {
				val = eval("this.e.currentStyle." + this.jsProperty(p));
			}
			else {
				val = null;
			}
		}
		else {
			var style = document.defaultView.getComputedStyle(this.e,"");
			if (style != null) { val = style.getPropertyValue(p); }
		}
		if (p != null && returnInt) {
			val = parseInt(val);
			if (isNaN(val)) { val = 0; }
		}
		return val;
	};
	
	
	this.getInt = function (p) {
		return this.get(p, true);
	};
	
	
	this.hasClass = function (c) {
		var test = " " + this.e.className + " ";
		if (test.indexOf(" " + c + " ") > -1) {
			return true;
		}
		return false;
	};
	
	
	this.addClass = function (c) {
		if (!this.hasClass(c)) { 
			if (this.e.className) {
				 this.e.className += " " + c;	
			}
			else {
				this.e.className = c;
			}
		}
	};
	
	
	this.removeClass = function (c) {
		var re = new RegExp(" " + c + " ");
		this.e.className = trim((" " + this.e.className + " ").replace(re, ''));
	};

	
	this.jsProperty = function (p) {
		return p.replace(this.propRegExp, 
			function (str, m1) {
				return m1.toUpperCase();
			}
		); 
	};
			
	
};


/* *** BROWSER FUNCS ************************************************************************** */


function Browser () {

	this.IE      = false;
	this.MOZILLA = false;
	this.WEBKIT  = false;
	this.OPERA   = false;
	this.name    = ""; 
	this.ver     = 0; 
	
	this.construct = function () {
		var appVer = navigator.appVersion;
		var agent = navigator.userAgent;
		if (window.opera) {
			this.OPERA = true;
			this.ver = opera.version();
			this.name = "Opera";
		}
		else if (appVer.indexOf("MSIE") > -1 && document.all) {
			var start = appVer.indexOf("MSIE ") + 5;
			this.IE = true;
			this.ver = parseFloat(appVer.substring(start, appVer.indexOf(";", start)));
			this.name = "Internet Explorer";
		}
		else if (appVer.indexOf("WebKit") > -1) {
			var start = appVer.indexOf("WebKit/") + 7;
			this.WEBKIT = true;
			this.ver = parseFloat(appVer.substring(start, appVer.indexOf(" (", start)));
			this.name = "Webkit";
		}
		else {
			this.MOZILLA = true;
			if (navigator.userAgent.indexOf("Firefox") > -1) {
				this.ver = parseFloat(agent.substring(agent.lastIndexOf("/")+1));
				this.name = "Firefox";
			}
			else {
				var start = agent.indexOf("rv:") + 3;
				this.ver = parseFloat(agent.substring(start, agent.indexOf(")", start)));
				this.name = "Mozilla";
			}
		}
		
		//alert(this.name + " " + this.ver);
	};
	
	
	this.getInnerWidth = function () {
		if (self.innerWidth) {
			return self.innerWidth;
		}
		else if (document.documentElement && document.documentElement.clientWidth) {
			return document.documentElement.clientWidth;
		}			
		else if (document.body && document.body.clientWidth) {
			return document.body.clientWidth;
		}
		return 0;
	};
	
	
	this.getInnerHeight = function () {
		if (window.innerHeight) {
			return window.innerHeight;
		}
		else if (document.documentElement && document.documentElement.clientHeight) {
			return document.documentElement.clientHeight;
		}				
		else if (document.body && document.body.clientHeight) {
			return document.body.clientHeight;
		}
		return 0;
	};

	
	this.getScrollTop = function () {
		if (typeof pageYOffset!= 'undefined') {
			//most browsers
			return pageYOffset;
		}
		else {
        var B= document.body; //IE 'quirks'
        var D= document.documentElement; //IE with doctype
        D= (D.clientHeight)? D: B;
        return D.scrollTop;
		}
	};


	this.getScrollHeight = function () {
		return site.dom.getBody().scrollHeight;
	};


	this.scrollTo = function (targetScrollTop, steps, delay) {
		var start = this.getScrollTop();
		var distance = targetScrollTop - start;
		var radius = distance/2;
		var circle = new Circle({ 'x':radius, 'y':0 }, radius);
		var queue = new Queue("windowScroll",  true);

		for (var i=0; i < 180; i+=(180/steps)) {
			queue.push(
				function (top) {
					window.scrollTo(0, top);
				},
				[circle.getPosition(i-90).x + start],
				delay
			);
		}		
		return queue;
	};	

	
	this.onEvent = function (evName, action) {
		if (window.addEventListener) {
			window.addEventListener(evName, action, false);
		}
		else if (window.attachEvent) {
			window.attachEvent(evName, action);
		}
	};
	
	
	this.stopEvent = function (ev) {
		ev = (ev || window.event);
		if (ev) {
			if (ev.stopPropagation) {
				ev.stopPropagation();
			}
			ev.cancelBubble = true;
		}			
	};
	
	
	this.construct();
}


/* *** QUEUE FUNCS ************************************************************************** */

function Queue (name, autoAdvance) {

	var thisthis = this; //used in lambda funcs

	this.actions = [];
	this.name = name;
	this.autoAdvance = autoAdvance;
	this.timer = null;

	this.construct = function () {
		if (site.queues[this.name]) {
			site.queues[this.name].stop();
		}
		site.queues[this.name] = this;		
	};
	
	this.push = function (func, args, delay) {
		this.add(func, args, false, delay);
	};
	
	this.unshift = function (func, args, delay) {
		this.add(func, args, true, delay);
	};
	
	this.add = function (func, args, top, delay) {
		if (!args) {
			args = [];	
		}
		else if (!isArray(args)) {
			args = [args];
		}
		if (top) {
			this.actions.unshift(new this.Action(func, args, delay));
		}
		else {
			this.actions.push(new this.Action(func, args, delay));
		}
		if (this.timer == null && this.autoAdvance) {
			this.next();
		}
	};
	
	this.next = function () {
		this.clearTimeout();
		if (this.actions.length > 0) {
			var action = thisthis.actions.shift();
			if (action.delay) {
				this.timer = setTimeout(
					function () { 
						action.run();
						delete action;
						if (thisthis.autoAdvance) {
							thisthis.next();
						}
					}, 
					action.delay
				);
			}
			else {
				action.run();
			}
		}
	};
	
	this.addPause = function (ms) {
		this.push(function () {true;}, [], ms);
	};
	
	this.stop = function () {
		this.clearTimeout();
		site.queues[name] = null;
	};
	
	this.clearTimeout = function () {
		clearTimeout(this.timer);
		this.timer = null;
	};
	

	this.Action = function (func, args, delay) {
		this.func = func;
		this.args = args;
		this.delay = delay ? delay : 1;
		
		this.run = function () {
			this.func.apply(this, args);
		};
	};	
	
	this.construct();
	
}


/* *** CIRCLE OBJECT ************************************************************************** */

function Circle (midpoint, radius) {
	
	this.midpoint = midpoint;
	this.radius = radius;
	
	this.getPosition = function (angle) {
		var x = this.midpoint.x + Math.round(this.radius * Math.sin(toRadians(angle)));
		var y = this.midpoint.y + Math.round(this.radius * Math.cos(toRadians(angle)));
		return { 'x':x, 'y':y };
	};
}




/* *** GLOBAL FUNCS ************************************************************************** */


function $ (id) {
	if (isArray(id)) {
		//is an array
		for (var i=0; i < id.length; i++) {
			id[i] = site.dom.get(id);
		}
		return id;
	}
	else {
		return site.dom.get(id);
	}
}


function toRadians (d) {
	return d * (Math.PI/180);
}


function trim (str) {
	if (str) {
		return str.replace(site.regexp['trim'],"");
	}
	else {
		return '';
	}
}


function isArray (obj) {
	if (typeof obj == 'object' && obj.length != null && obj.pop) {
		return true;
	}
	return false;
}


function stringRepeat (string, num) {
	var rString = '';
	for (var i=0; i < num; i++) {
		rString+= string;
	}
	return rString;
}
