var currentFancyBox,
globalLang;

// I18N
if (window.i18n === undefined) {
	window.i18n = {};
}

function __(str) {
	arguments[0] = window.i18n[globalLang] && window.i18n[globalLang][str] ? window.i18n[globalLang][str] : str;
	return sprintf.apply(null, arguments);
}


$(function() {
	globalLang = $("html").attr("lang");
	
	// external links
	$("a[rel=external]").attr("target", "_blank");

	// links to other sites
	$("a[href^=http]:not(.external_ok)").each(function() {
		var href = this.href;
		var host = parse_url(href, 'PHP_URL_HOST');
		if (host !== document.location.host && "www." + host !== document.location.host) {
			// $(this).attr("target", "_blank");
			
			// IE sets this for some reason, super helpfulfulfufl!!!1
			var html = this.innerHTML;
			this.href = document.location.protocol + "//" + document.location.host + "/speedbump?external_url=" + encodeURIComponent(base64_encode(href)) + "&prev_url=" + encodeURIComponent(base64_encode(document.location.href));
			this.innerHTML = html;
		}
	});
	
	// PDFs 
	$("a[href$=\".pdf\"]").attr("target", "_blank");
	
	// Placeholders
	$("input[type=text][title]").each(function() {
		$(this).data("placeholder", this.title).bind("focus", function() {
			if (this.value == $(this).data("placeholder")) {
				this.value = "";
			}
			$(this).removeClass("default");
		}).bind("blur", function() {
			if (this.value == "" || this.value == $(this).data("placeholder")) {
				this.value = $(this).data("placeholder");
				$(this).addClass("default");
			}
		}).attr("title", "").trigger("blur").closest("form").bind("submit", function(evt) {
			$(this).find("input[type=text][title], textarea[title]").each(function() {
				$(this).triggerHandler("focus");
			});
		});
	});
	
	// Fancy Box
	var fancyBoxes = $('a[rel=fancy_box]').each(function() {
		if (!window.ie6) {
			var fn = $(this);
			fn.addClass("with_caption").append("<span class=\"fancy_box_icon\"><\/span>\
			<span class=\"fancy_box_caption\" style=\"width:" + fn.width() + "px;\">" + __('Click to Enlarge') +  "<\/span>");
		}
		
	}).fancybox();
	
	$("input").each(function() {
		$(this).addClass('input_' + $(this).attr("type"));
	});
	
	$('label[for]').each(function() {
		var fn = $(this);
		var input = $("#" + this.htmlFor);
		if (input.length > 0) {
			input.bind("focus", function() {
				fn.addClass("focus");
			}).bind("blur", function() {
				fn.removeClass("focus");
			});
		}
	});
	
	// Image captions
	$(".image_caption").each(function() {
		var fn = $(this);
		var img = fn.find("img[alt!='']");
		if (img.length > 0) {
			fn.width(img.width());
			fn.append("<div class=\"caption\">" + __(img.attr("alt")) + "<\/div>");
		}
	});
	
	// Image borders
	$(".image_border").each(function() {
		var fn = $(this);
		var img = fn.find("img");
		if (img.length > 0) {
			fn.width(img.width());
			fn.append("<div class=\"hr\"><\/div>");
		}
	});
	
	// Video links
	$(".multimedia_element").each(function() {
		var fn = $(this);
		var anchor = fn.find("a[href$=\".mp4\"]").each(function() {
			$(this).bind("click", function() {
				currentFancyBox = $(this);
				
			}).attr('href', "/video?video=" + encodeURIComponent(this.href)).fancybox({
				width: 864,
				height: 486,
				type: 'iframe'
			});
		});
		
		var img = fn.find("img[alt!='']");
		var caption = fn.find(".caption");
		fn.width(img.width());
		if (img.length > 0 && caption.length === 0) {
			var alt = img.attr("alt") || "";
			var pieces = alt.split(":");
			var caption = pieces.length > 1 ? "<strong>" + pieces.shift() + ":</strong>" + pieces.join(":") : pieces.join(":");
			fn.append("<div class=\"caption\">" + caption + "<\/div>");
		}
	});
	
	$(".image_list li").each(function() {
		var el = $(this);
		var left = el.find("> .left");
		var right = el.find("> .right");
		if (left.length && right.length) {
			right.width(660 - left.width() - 15);
		}
	});
	
	// Fix the TissuGlu r-balls
	findAndReplace(/(?!<sup>)(®)(?!<\/sup>)/ig, "<sup>®</sup>", $("body")[0]);
	
	// Navigation drops downs
	var navDuration = 150,
	timeoutDuration = 100;

	$("#navigation > ul > li").each(function() {

		var li = $(this);
		var fn = li.find(" > ul");

		var newFn = fn.clone(true);
		fn.remove();

		var wrapper = $("#wrapper");
		var nav = $("#navigation");

		newFn.appendTo(wrapper).addClass("nav_dropdown").css({
			top: li.position().top + li.height() + nav.position().top,
			left: li.position().left + nav.position().left
			
		}).hover(function() {
			openNavUL(this);
			
		}, function() {
			closeNavUL(this);
			
		}).find("> li:not(.last)").each(function() {
			$(this).find(".last").removeClass("last");
		});
		
		newFn.find("> .last").each(function() {
			var lastEl = $(this);
			var lastChildren = lastEl.find("> ul > li.last");
			if (lastChildren.length) {
				lastEl.removeClass("last");
			}
		});
		
		newFn.css({
			visibility: 'hidden',
			height: 'auto',
			minWidth: li.width()
			
		}).data("height", newFn.height()).css({
			visibility: 'visible',
			height: 0
		});
		
		// Set width for IE6 and 7 to prevent li bug
		var liWidth = 0;
		newFn.find(" > li").each(function() {
			var width = $(this).width();
			if (liWidth < width) {
				liWidth = width;
			}
		}).width(liWidth);
		
		li.data('ul', newFn);

	}).hover(function() {
		openNavUL($(this).data('ul'));

	}, function() {
		closeNavUL($(this).data('ul'));
	});

	function openNavUL(ul) {
		ul = $(ul);
		clearTimeout(ul.data("timeout"));
		ul.stop().animate({
			height: ul.data('height')
		}, navDuration);
	}

	function closeNavUL(ul) {
		ul = $(ul);
		ul.data('timeout', setTimeout(function() {
			ul.stop().animate({
				height: 0
			}, navDuration);
		}, timeoutDuration));
	}
	
	
});

if (!Array.indexOf) {
	Array.prototype.indexOf = function(obj) {
		for (var i=0; i<this.length; i++) {
			if (this[i]==obj) {
				return i;
			}
		}
		return -1;
	}
}

!Modernizr.cssgradients && $(function() {
	$("#navigation > ul > li").append("<div class=\"nav_bg\"><div> <\/div><\/div>");
});

window.ie6 && $(function() {
	$("#navigation > ul > li").each(function() {
		$(this).width($(this).width());
	});
});


function base64_encode (data) {
    // Encodes string using MIME base64 algorithm  
    // 
    // version: 1004.2314
    // discuss at: http://phpjs.org/functions/base64_encode
    // +   original by: Tyler Akins (http://rumkin.com)
    // +   improved by: Bayron Guevara
    // +   improved by: Thunder.m
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Pellentesque Malesuada
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // -    depends on: utf8_encode
    // *     example 1: base64_encode('Kevin van Zonneveld');
    // *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
    // mozilla has this native
    // - but breaks in 2.0.0.12!
    //if (typeof this.window['atob'] == 'function') {
    //    return atob(data);
    //}
        
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = [];

    if (!data) {
        return data;
    }

    data = utf8_encode(data+'');
    
    do { // pack three octets into four hexets
        o1 = data.charCodeAt(i++);
        o2 = data.charCodeAt(i++);
        o3 = data.charCodeAt(i++);

        bits = o1<<16 | o2<<8 | o3;

        h1 = bits>>18 & 0x3f;
        h2 = bits>>12 & 0x3f;
        h3 = bits>>6 & 0x3f;
        h4 = bits & 0x3f;

        // use hexets to index into b64, and append result to encoded string
        tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
    } while (i < data.length);
    
    enc = tmp_arr.join('');
    
    switch (data.length % 3) {
        case 1:
            enc = enc.slice(0, -2) + '==';
        break;
        case 2:
            enc = enc.slice(0, -1) + '=';
        break;
    }

    return enc;
}

function utf8_encode ( argString ) {
    // Encodes an ISO-8859-1 string to UTF-8  
    // 
    // version: 1004.2314
    // discuss at: http://phpjs.org/functions/utf8_encode
    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: sowberry
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +   improved by: Yves Sucaet
    // +   bugfixed by: Onno Marsman
    // +   bugfixed by: Ulrich
    // *     example 1: utf8_encode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'
    var string = (argString+''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");

    var utftext = "";
    var start, end;
    var stringl = 0;

    start = end = 0;
    stringl = string.length;
    for (var n = 0; n < stringl; n++) {
        var c1 = string.charCodeAt(n);
        var enc = null;

        if (c1 < 128) {
            end++;
        } else if (c1 > 127 && c1 < 2048) {
            enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
        } else {
            enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
        }
        if (enc !== null) {
            if (end > start) {
                utftext += string.substring(start, end);
            }
            utftext += enc;
            start = end = n+1;
        }
    }

    if (end > start) {
        utftext += string.substring(start, string.length);
    }

    return utftext;
}


function findAndReplace(searchText, replacement, searchNode) {
    if (!searchText || typeof replacement === 'undefined') {
        // Throw error here if you want...
        return;
    }
    var regex = typeof searchText === 'string' ?
                new RegExp(searchText, 'g') : searchText,
        childNodes = (searchNode || document.body).childNodes,
        cnLength = childNodes.length,
        excludes = 'html,head,style,title,link,meta,script,object,iframe';
    while (cnLength--) {
        var currentNode = childNodes[cnLength];
        if (currentNode.nodeType === 1 &&
            (excludes + ',').indexOf(currentNode.nodeName.toLowerCase() + ',') === -1) {
            arguments.callee(searchText, replacement, currentNode);
        }
        if (currentNode.nodeType !== 3 || !regex.test(currentNode.data) ) {
            continue;
        }
        var parent = currentNode.parentNode,
            frag = (function(){
                var html = currentNode.data.replace(regex, replacement),
                    wrap = document.createElement('div'),
                    frag = document.createDocumentFragment();
                wrap.innerHTML = html;
                while (wrap.firstChild) {
                    frag.appendChild(wrap.firstChild);
                }
                return frag;
            })();
        parent.insertBefore(frag, currentNode);
        parent.removeChild(currentNode);
    }
}


function parse_url (str, component) {
    // Parse a URL and return its components  
    // 
    // version: 1004.2314
    // discuss at: http://phpjs.org/functions/parse_url
    // +      original by: Steven Levithan (http://blog.stevenlevithan.com)
    // + reimplemented by: Brett Zamir (http://brett-zamir.me)
    // %          note: Based on http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
    // %          note: blog post at http://blog.stevenlevithan.com/archives/parseuri
    // %          note: demo at http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
    // %          note: Does not replace invaild characters with '_' as in PHP, nor does it return false with
    // %          note: a seriously malformed URL.
    // %          note: Besides function name, is the same as parseUri besides the commented out portion
    // %          note: and the additional section following, as well as our allowing an extra slash after
    // %          note: the scheme/protocol (to allow file:/// as in PHP)
    // *     example 1: parse_url('http://username:password@hostname/path?arg=value#anchor');
    // *     returns 1: {scheme: 'http', host: 'hostname', user: 'username', pass: 'password', path: '/path', query: 'arg=value', fragment: 'anchor'}
    var  o   = {
        strictMode: false,
        key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
        q:   {
            name:   "queryKey",
            parser: /(?:^|&)([^&=]*)=?([^&]*)/g
        },
        parser: {
            strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
            loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/\/?)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // Added one optional slash to post-protocol to catch file:/// (should restrict this)
        }
    };
    
    var m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
    uri = {},
    i   = 14;
    while (i--) {uri[o.key[i]] = m[i] || "";}
    // Uncomment the following to use the original more detailed (non-PHP) script
    /*
        uri[o.q.name] = {};
        uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
        if ($1) uri[o.q.name][$1] = $2;
        });
        return uri;
    */

    switch (component) {
        case 'PHP_URL_SCHEME':
            return uri.protocol;
        case 'PHP_URL_HOST':
            return uri.host;
        case 'PHP_URL_PORT':
            return uri.port;
        case 'PHP_URL_USER':
            return uri.user;
        case 'PHP_URL_PASS':
            return uri.password;
        case 'PHP_URL_PATH':
            return uri.path;
        case 'PHP_URL_QUERY':
            return uri.query;
        case 'PHP_URL_FRAGMENT':
            return uri.anchor;
        default:
            var retArr = {};
            if (uri.protocol !== '') {retArr.scheme=uri.protocol;}
            if (uri.host !== '') {retArr.host=uri.host;}
            if (uri.port !== '') {retArr.port=uri.port;}
            if (uri.user !== '') {retArr.user=uri.user;}
            if (uri.password !== '') {retArr.pass=uri.password;}
            if (uri.path !== '') {retArr.path=uri.path;}
            if (uri.query !== '') {retArr.query=uri.query;}
            if (uri.anchor !== '') {retArr.fragment=uri.anchor;}
            return retArr;
    }
}

function sprintf ( ) {
    // Return a formatted string  
    // 
    // version: 1004.2314
    // discuss at: http://phpjs.org/functions/sprintf
    // +   original by: Ash Searle (http://hexmen.com/blog/)
    // + namespaced by: Michael White (http://getsprink.com)
    // +    tweaked by: Jack
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Paulo Ricardo F. Santos
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: sprintf("%01.2f", 123.1);
    // *     returns 1: 123.10
    // *     example 2: sprintf("[%10s]", 'monkey');
    // *     returns 2: '[    monkey]'
    // *     example 3: sprintf("[%'#10s]", 'monkey');
    // *     returns 3: '[####monkey]'
    var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
    var a = arguments, i = 0, format = a[i++];

    // pad()
    var pad = function (str, len, chr, leftJustify) {
        if (!chr) {chr = ' ';}
        var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
        return leftJustify ? str + padding : padding + str;
    };

    // justify()
    var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
        var diff = minWidth - value.length;
        if (diff > 0) {
            if (leftJustify || !zeroPad) {
                value = pad(value, minWidth, customPadChar, leftJustify);
            } else {
                value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
            }
        }
        return value;
    };

    // formatBaseX()
    var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
        // Note: casts negative numbers to positive ones
        var number = value >>> 0;
        prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';
        value = prefix + pad(number.toString(base), precision || 0, '0', false);
        return justify(value, prefix, leftJustify, minWidth, zeroPad);
    };

    // formatString()
    var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
        if (precision != null) {
            value = value.slice(0, precision);
        }
        return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
    };

    // doFormat()
    var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
        var number;
        var prefix;
        var method;
        var textTransform;
        var value;

        if (substring == '%%') {return '%';}

        // parse flags
        var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, customPadChar = ' ';
        var flagsl = flags.length;
        for (var j = 0; flags && j < flagsl; j++) {
            switch (flags.charAt(j)) {
                case ' ': positivePrefix = ' '; break;
                case '+': positivePrefix = '+'; break;
                case '-': leftJustify = true; break;
                case "'": customPadChar = flags.charAt(j+1); break;
                case '0': zeroPad = true; break;
                case '#': prefixBaseX = true; break;
            }
        }

        // parameters may be null, undefined, empty-string or real valued
        // we want to ignore null, undefined and empty-string values
        if (!minWidth) {
            minWidth = 0;
        } else if (minWidth == '*') {
            minWidth = +a[i++];
        } else if (minWidth.charAt(0) == '*') {
            minWidth = +a[minWidth.slice(1, -1)];
        } else {
            minWidth = +minWidth;
        }

        // Note: undocumented perl feature:
        if (minWidth < 0) {
            minWidth = -minWidth;
            leftJustify = true;
        }

        if (!isFinite(minWidth)) {
            throw new Error('sprintf: (minimum-)width must be finite');
        }

        if (!precision) {
            precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : undefined;
        } else if (precision == '*') {
            precision = +a[i++];
        } else if (precision.charAt(0) == '*') {
            precision = +a[precision.slice(1, -1)];
        } else {
            precision = +precision;
        }

        // grab value using valueIndex if required?
        value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];

        switch (type) {
            case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
            case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
            case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
            case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'i':
            case 'd':
                number = parseInt(+value, 10);
                prefix = number < 0 ? '-' : positivePrefix;
                value = prefix + pad(String(Math.abs(number)), precision, '0', false);
                return justify(value, prefix, leftJustify, minWidth, zeroPad);
            case 'e':
            case 'E':
            case 'f':
            case 'F':
            case 'g':
            case 'G':
                number = +value;
                prefix = number < 0 ? '-' : positivePrefix;
                method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
                textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
                value = prefix + Math.abs(number)[method](precision);
                return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
            default: return substring;
        }
    };

    return format.replace(regex, doFormat);
}

