/* LEGAL COPYRIGHT NOTICE

Copyright (c) Noble Samurai Pty Ltd, 2008-2011.  All Rights Reserved.  

This software is proprietary to and embodies the confidential technology of Noble Samurai Pty Ltd.  Possession, use, dissemination or copying of this software and media is authorised only pursuant to a valid written license from Noble Samurai Pty Ltd.  Questions or requests regarding permission may be sent by email to legal@noblesamurai.com or by post to PO Box 477, Blackburn Victoria 3130, Australia.

*/

/*

NobleSamurai common Javascript functions

*/


//ApplyZebra - Blatantly thieved from bazooka.admin.js
var realAjax = jQuery.ajax;
var realComplete = null;

jQuery.extend({
	/* this seems to break (element).load(url) intermittently... not sure why...  
	ajax: function(settings) {		//this is an override to jquery's ajax functions which does login redirects when on the account system
		if (typeof(settings) == 'object' && settings.url.match('/account/') ) { //only requests to 'account'
			realComplete = settings.complete;
			//settings-only call...
			jQuery.extend(settings,{
				complete: function(jqXHR,status) {
					if (jqXHR.status == 403) {
						//redirect to login screen...
						var loc = window.location.href
						loc.replace('/account/','/account/login?oldAction=')  //this is a bit nasty, but it works!
						window.location = loc;
					}
					if (realComplete) {
						realComplete();
					}
				}
			})
		}
		return realAjax(settings);
	},
	/**/
	dechex: function(dec) {
		return ((dec < 16) ? "0" : "") + dec.toString(16);
	},
	zebraDecay: function(x) {
		return parseInt(Math.max(x - 16, 0, x * 0.8));
	},
	formatDateWithTime: function(format,dt) {
		if (!format) format = "yy-mm-dd";
		var strDate = $.datepicker.formatDate("yy-mm-dd",dt),
			hr = dt.getHours(),
			min = dt.getMinutes()
		return strDate + (hr<10?' 0':' ') + hr + ':' + (min<10?'0':'') + min
	}
});

jQuery.fn.extend({
	
	//center an item in its parent...
	centerInParent: function() {
		var obj = jQuery(this),
			par = obj.parent();
		obj.css({
			position: 'absolute',
			left: parseInt((par.outerWidth() / 2) - (obj.outerWidth() / 2)) + 'px',
			top: parseInt((par.outerHeight() /2) - (obj.outerHeight() / 2)) + 'px'
		})
		return obj;
	},
	
	// do a pretty grey overlay, i.e for ajax load...
	//	state may be:
	//		* null 				- toggle visibility
	//		* true / false		- set visibility	
	//		* a string			- html to go in the grey out area. if 
	//								you pass a string and a greyout is already
	//								visible, content is updated.
	greyOut: function(state) {
		var obj = jQuery(this),
			isGrey = (obj.find('.greyOut').length > 0)
			
		if (state == null)	//no param, toggle... 
			state = !isGrey
			
		if (!obj.is(':visible') && state) return false; //you can't grey-out an invisible element, but you can un-grey it
		
		if (isGrey && !state) {	//hide existing...
			jQuery(this).find('.greyOut').remove()
		} else if (!isGrey && state) {	//grey out...
			var content = ''
			if (state != true) content = state	//unfocus...
			obj.find('*').each(function(){this.blur()});
			return $('<div class="greyOut">' + content + '</div>').css( {
			    position: 'absolute',
			    top: obj.position().top + 'px',
			    left: obj.position().left +  'px',
			    width: obj.outerWidth() + 'px',
			    height: obj.outerHeight() + 'px',
			    'background': 'rgba(0,0,0,0.5)'
			}).appendTo(obj);
		} else if (isGrey && state) { //work with existing div...
			if (state != true) 
				return obj.find('.greyOut').first().html(state); //update content
			return obj.find('.greyOut').first();
		}
				
	},
	
	// highlight alternative table rows
	applyZebra: function() {
		if (jQuery(this).hasClass('noZebra')) return;
		
		jQuery('tr:nth-child(odd)', this).each(function(){
			var row = jQuery(this);
				
			if (row.hasClass('odd') || row.hasClass('even')) return true;
			
			var rowBg = row.css('background-color');
			
			// TODO: determine which browsers will say if tds are transparent
			// and allow us skip processing those tds
			row.children('td').each(function(){
				
				var cell = jQuery(this);
					
				if (cell.hasClass('footer') || cell.hasClass('noZebra')) return true;
					
				var r=-1, g=-1, b=-1;
				
				// get colour from cell
				var oc = cell.css('background-color');
				if (typeof oc=="undefined" || oc == "transparent" || oc == 'rgba(0, 0, 0, 0)') {
					// try to get colour from row
					oc = rowBg;
				}
				if (typeof oc=="undefined" || oc == "transparent" || oc == 'rgba(0, 0, 0, 0)') {
					r = g = b = 255;
					
				} else {
					
					if (oc.length == 4 && oc.substr(0,1) == '#') { // handle short values
						oc = "#"+oc.charAt(1)+oc.charAt(1)+oc.charAt(2)+
							oc.charAt(2)+oc.charAt(3)+oc.charAt(3);
					}
					if (oc.length == 7 && oc.substr(0,1) == '#') {
						r=parseInt(oc.substr(1,2),16);
						g=parseInt(oc.substr(3,2),16);
						b=parseInt(oc.substr(5,2),16);
				
					} else if (oc.substr(0,4) == 'rgb(') {
						var rgb = oc.substr(4,oc.length-5).split(",");
						r = rgb[0];
						g = rgb[1];
						b = rgb[2];
					} else {
						/* if it's a named colour, we don't know how to interpret it
						*  so will do nothing to it
						*
						*  Note that Firefox will store named colours as their RGB values
						*  but IE & opera won't
						*/
						//alert(oc);
					}
				}
				
				if (r >= 0 && g >= 0 && b >= 0) {
					// get darker colour from original
					r = jQuery.zebraDecay(r);
					g = jQuery.zebraDecay(g);
					b = jQuery.zebraDecay(b);
					cell.css('background-color', "#"+jQuery.dechex(r)+jQuery.dechex(g)+jQuery.dechex(b));
				}
			});
		});
	}
});

function resizePopup() {
	//resize our popup div, and correctly place the popup window...
	var doc = $(document);
	var win = $(window);
	var box = $('#popupBox').is(':visible') ? 
			$("#popupBox") : 
			$("#spinnerDiv"); //$("#popupBox");
	var div = $("#popupDiv");

	//size the background...
	$("#popupDiv").height(
			doc.height() > win.height() ? doc.height() : win.height()
			).width(doc.width());

	box.css('left',(win.width() / 2) - (div.width() / 2));
	//resizing weirdness in chrome / safari: this seems to fix it. don't ask me why.
	box.css('left',(win.width() / 2) - (box.width() / 2));
	
	var winTopOffset = box.height() >= win.height() ? 155 : (win.scrollTop()>155 ? win.scrollTop() + 30 : 155); //155 - minimum offset for top of popup window...

	///todo: take scrolling into account to center *in view*
	if (box.height() >= win.height()) {
		box.css('top',winTopOffset);
	} else { 
		box.css('top',(win.height()/2) - (box.height() / 2) + win.scrollTop());
	}

	//popup shouldn't cover the header...
	if (box.css('top') < winTopOffset) { box.css('top',winTopOffset); }
	
	//ensure that the faded background covers the whole page (i.e if box is too tall)...
	if ((box.height() + parseInt(box.css('top'))) > $("#popupDiv").height()) $("#popupDiv").height(box.height() + parseInt(box.css('top')));
	
/*
	console.log($("#popupDiv").height());
	console.log(box.height());
	console.log(win.height());
	console.log(doc.height());
*/	
}
$(window).resize(function() {
	if ($('#popupDiv').is(':visible'))
		resizePopup();
});

function showPopupWindow(titleHtml,innerHtml,style) {
	$("#spinnerDiv").hide();
	$("#popupBox").css("display","block");
	var popup = $("#popupDiv"); 
	//make greyed-out area cover entire page...		
	popup.height($(document).height());

	$("#popupTitle").html(titleHtml);

	// Accept a jQuery object as well as string
	if (typeof innerHtml == 'string') {
		$("#popupContent").html(innerHtml);
	} else {
		$("#popupContent").contents().replaceWith($(innerHtml).contents().clone());
	}

	//HACK: 'display' the div off-screen to determine its width...
	popup.css('left',-10000);
	popup.css('top',-10000);
	popup.show();
	//position the popup (needs to be visible, unfortunately, hence hack)...
	resizePopup();
	//now pretend we never did a hack...
	popup.hide();

	popup.css('z-index', 1000);
	
	//show the popup...
	popup.css('left',0);
	popup.css('top',0);
	popup.fadeIn(333);
}

function hidePopupWindow() {
	//$('#popupDiv').hide()
	$('#popupDiv').fadeOut(333);
}

function showSpinner(captionHtml) {
	$("#popupBox").hide();
	$("#spinnerDiv").css("display","block");
	$("#spinnerCaption").html(captionHtml);
	var popup = $("#popupDiv");
	popup.css('left',-10000);
	popup.css('top',-10000);
	popup.show();
	//position the popup (needs to be visible, unfortunately, hence hack)...
	resizePopup();
	//now pretend we never did a hack...
	popup.hide();
	
	//show the popup...
	popup.css('left',0);
	popup.css('top',0);
	popup.fadeIn(333);
	$("#popupDiv").fadeIn(333);
	
}

function ajaxPopup(url,loadingText,titleHtml) {
	//show a pretty spinner while doing an ajax load, then 
	//display a pretty popup window containing the results of the load.

	if (loadingText == '') loadingText = 'Loading...';
	if (titleHtml == '') titleHtml = 'Result'; 
	$("#popupTitle").html(titleHtml);
	showSpinner(loadingText);
	$("#popupContent").load(url,function() {
		$("#spinnerDiv").hide();
		var popup = $("#popupBox");
		popup.css('left',-10000);
		popup.css('top',-10000);
		popup.show();
		resizePopup();
		popup.hide;
		popup.fadeIn(333);
	});
}

function doCountDown(selector,secondsRemaining) {
	if (secondsRemaining == Infinity) {
		$(selector).html("Infinity");
		return true;
	} else if(secondsRemaining <= 0) {
		days = "00";
		hours = "00";
		mins = "00";
		secs = "00";
	} else {
		var rem = secondsRemaining;
		var days = Math.floor(rem / (60 * 60 * 24));
		rem -= days * 60 * 60 * 24;
		if (days < 10) {
			days = "0" + days.toString();
		}			
		
		var hours = Math.floor(rem / (60 * 60));
		rem -= hours * (60 * 60);
		if (hours < 10) {
			hours = "0" + hours.toString();
		}
		
		var mins = Math.floor(rem / 60) ;
		rem -= mins * 60;
		if (mins < 10) {
			mins = "0" + mins.toString();
		}
		
		var secs = Math.floor(rem) ;
		if (secs < 10) {
			secs = "0" + secs.toString();
		}
	}
	
	$(selector).text(days + ':' + hours + ':' + mins + ':' + secs);
	//call self again...
	window.setTimeout('doCountDown(\'' + selector + '\',' + (parseInt(secondsRemaining) - 1).toString() +')',1000);
	
}

function selectMenu(menuText, menu) {
	if (!menuText) return false;

	if (!menu || menu == "nav-wrapper")
		if ($("#nav-wrapper li a:contains('" + menuText + "')").addClass('selectedNavItem').length)
			return true;

	if (!menu || menu == "nav-smallwrapper")
		if ($("#nav-smallwrapper li a:contains('" + menuText + "')").addClass('selectedNavItem').length)
			return true;

	if (!menu || menu == "nav-smallerwrapper")
		if ($("#nav-smallerwrapper li a:contains('" + menuText + "')").addClass('selectedNavItem').length)
			return true;
	
	return false;
}

// basic ajax page updates.
function ajaxUpdate(url, request) {
	request = request || {};
	request.ajax = 1;
	$.ajax({
		type		: 'POST',
		url			: url,
		dataType	: 'json',
		data		: request,
		success		: function(response) {
			for (var i in response) {
				var item = $(i);
				if (item.length) {
					switch (response[i]) {
						case true:
							item.show();
							break;
						case false:
							item.hide();
							break;
						default:
							if (item.is('input')) item.val(response[i]);
							else item.text(response[i]);
					}
				}
			}
		}
	});
}

/**
 * taken from: http://www.vbknowledgebase.com/?Id=80&Desc=Javascript-Date-functions-for-VB-DateDiff-DateAdd
 */
function dateAdd(ItemType, DateToWorkOn, ValueToBeAdded)
{
    switch (ItemType)
    {
        //date portion        
        case 'd': //add days
            DateToWorkOn.setDate(DateToWorkOn.getDate() + ValueToBeAdded)
            break;
        case 'm': //add months
            DateToWorkOn.setMonth(DateToWorkOn.getMonth() + ValueToBeAdded)
            break;
        case 'y': //add years
            DateToWorkOn.setYear(DateToWorkOn.getFullYear() + ValueToBeAdded)
            break;
        //time portion        
        case 'h': //add days
            DateToWorkOn.setHours(DateToWorkOn.getHours() + ValueToBeAdded)
            break;
        case 'n': //add minutes
            DateToWorkOn.setMinutes(DateToWorkOn.getMinutes() + ValueToBeAdded)
            break;
        case 's': //add seconds
            DateToWorkOn.setSeconds(DateToWorkOn.getSeconds() + ValueToBeAdded)
            break;
    }
    return DateToWorkOn;
}

/**
 * convert a localized date back to UTC
 * @param dt
 * @return
 */
function UTCFix(dt) {
	var dt2 = new Date();
	dt2.setDate(dt.getUTCDate())
	dt2.setMonth(dt.getUTCMonth())
	dt2.setFullYear(dt.getUTCFullYear())
	dt2.setHours(dt.getUTCHours())
	dt2.setMinutes(dt.getUTCMinutes())
	dt2.setSeconds(dt.getUTCSeconds())	
	return dt2
}

//DM: Hacked version of flot's formatDate function to use with local time
//		rather than flot's default UTC time.
// returns a string with the date d formatted according to fmt
var formatLocalDate = function(d, fmt, monthNames) {
    var leftPad = function(n) {
        n = "" + n;
        return n.length == 1 ? "0" + n : n;
    };
    
    var r = [];
    var escape = false, padNext = false;
    var hours = d.getHours();
    var isAM = hours < 12;
    if (monthNames == null)
        monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

    if (fmt.search(/%p|%P/) != -1) {
        if (hours > 12) {
            hours = hours - 12;
        } else if (hours == 0) {
            hours = 12;
        }
    }
    for (var i = 0; i < fmt.length; ++i) {
        var c = fmt.charAt(i);
        
        if (escape) {
            switch (c) {
            case 'h': c = "" + hours; break;
            case 'H': c = leftPad(hours); break;
            case 'M': c = leftPad(d.getMinutes()); break;
            case 'S': c = leftPad(d.getSeconds()); break;
            case 'd': c = "" + d.getDate(); break;
            case 'm': c = "" + (d.getMonth() + 1); break;
            case 'y': c = "" + d.getFullYear(); break;
            case 'b': c = "" + monthNames[d.getMonth()]; break;
            case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
            case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
            case '0': c = ""; padNext = true; break;
            }
            if (c && padNext) {
                c = leftPad(c);
                padNext = false;
            }
            r.push(c);
            if (!padNext)
                escape = false;
        }
        else {
            if (c == "%")
                escape = true;
            else
                r.push(c);
        }
    }
    return r.join("");
};

