(function() {

// temporary hack to make iContact Assist work with jQuery 1.3.2 (revert :hidden and :visible selectors to the 1.2.6 implementation)
$.expr[':'].visible = function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";};
$.expr[':'].hidden = function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";};
//trim from jQuery 1.4a2
$.trim = function( text ) {
	return (text || "").replace( /^(\s|\u00A0)+|(\s|\u00A0)+$/g, "" );
}

$.fn.fadeToggle = function(speed) {
	return this.each(function() {
		var elem = $(this);
		elem.is(':hidden') ? elem.fadeIn(speed) : elem.fadeOut(speed);
	});
};

// Resets a form without using <input type="reset" /> so we can style it ourselves
$.fn.resetForm = function() {
    return this.each(function() {
        var form = $(this).closest('form');
        if (form.length) {
            form[0].reset();
        }
    });
};

// app data
var icpData;


/** core functionality **/

var icp = (window.icp = {
	init: function(data) {
		icpData = data;
	},
	
	getName: function() {
		return icpData.name;
	},
	
	getSu: function() {
		return icpData.su;
	},
	
	getBaseUrl: function(url) {
		return icpData.appUrl + (url || '');
	},
	
	getBaseIncludeUrl: function(url) {
		return icpData.baseIncludeUrl + (url || '');
	},
	
	getCoreUrl: function(url) {
		return icp.getBaseUrl('/core' + (icpData.su ? '/~' + icpData.su : '') + (url || ''));
	},

	getHelpUrl: function(url) {
		return icpData.helpUrl + (url || '');
	},
	
	getTimeouts: function() {
		return {
			iClientTimeout: icpData.iClientTimeout,
			iServerTimeout: icpData.iServerTimeout,
			iServerTime: icpData.iServerTime,
			iNotificationMultiplier: icpData.iNotificationMultiplier
		};
	}
});

/** utilities **/

$.extend(icp, {
	now: function() {
		return +new Date();
	}
});

/** constants **/

icp.account = {
	PARTNER: 16
};

/** ajax **/

// builds a PHP-compatible query string from a hash
// includes support for arrays and hashes
function param(data) {
	// array of key=value pairs to build the query string
	var processed = [];
	
	// adds a key/value pair to the processed array
	// index is used for assoc and non-assoc arrays
	function add(key, value, index) {
		var encoded = encodeURIComponent(key);
		if (index != null) {
			encoded += '[' + encodeURIComponent(index) + ']';
		}
		encoded += '=' + encodeURIComponent(value);
		processed.push(encoded);
	}
	
	$.each(data, function(key, value) {
		// skip null/undefined
		if (value === null || value === undefined) { return; }
		
		// handle simple values
		if (typeof value == 'string' || typeof value == 'number') {
			add(key, value);
		// handle arrays
		} else if ($.isArray(value)) {
			$.each(value, function() {
				add(key, this, '');
			});
		// handle hashes
		} else {
			$.each(value, function(hashKey, hashValue) {
				add(key, hashValue, hashKey);
			});
		}
	});
	
	return processed.join('&').replace(/%20/g, '+');
}

icp.openWindow = function(url, data, windowProperties) {
	windowProperties = windowProperties || {};
	
	// set default size and positioning
	windowProperties.width = windowProperties.width || 300;
	windowProperties.height = windowProperties.height || 400;
	windowProperties.left = windowProperties.left || (screen.width - windowProperties.width) / 2;
	windowProperties.top = windowProperties.top || (screen.height - windowProperties.height) / 2;
	
	// set default window properties
	windowProperties = $.extend({
		scrollbars: 'yes',
		resizable: 'yes',
		menubar: 'yes',
		toolbar: 'yes'
	}, windowProperties);
	
	// add the data to the url
	url += '?' + param(data);
	
	// build a string of window properties
	var props = '';
	$.each(windowProperties, function(key, value) {
		props += key + '=' + value + ',';
	});
	
	return window.open(url, windowProperties.name, props);
}

// handles ajax calls to a controller and returns the result as json
// - data can be a hash containing strings, numbers, arrays, hashes
// - settings can be any valid settings for $.ajax (this is mostly useful for
//   passing extra data through to the callback method since all settings are
//   available in the callback method as properties of "this")
icp.ajax = function(url, data, settings, callback) {
	// allow the callback to be specified in any parameter after the url
	if ($.isFunction(data)) {
		callback = data;
		data = null;
	}
	if ($.isFunction(settings)) {
		callback = settings;
		settings = null;
	}
	data = data || {};
	
	$.ajax($.extend({
		type: 'post',
		dataType: 'json',
		url: url,
		success: callback,
		data: param(data)
	}, settings));
};


/** immediate setup **/

$(document).ready(function() {
	// setup help button
	$('#liHelpButton a').click(function() {
		window.open(this.href, this.target, "width=800,height=600,scrollbars=yes," +
			"status=yes,toolbar=yes,resizable=yes,menubar=yes,location=yes");
		return false;
	});
	
	// setup feedback buttons
	$('#liFeedbackButton a, #liGiveUsFeedback a').click(function() {
		window.open(this.href, this.target, "width=550,height=600,scrollbars=yes," +
			"status=no,toolbar=no,resizable=yes");
		return false;
	});
	
	// reset forms
	$('.resetForm').click(function() {
		$(this).resetForm();
	});
	
	(icpData.showHelp && icp.helpbar.toggle(false));
	(window.doOnload && doOnload());

	// set up datepickers
	// borrowed/stolen from the old calendar.js
	$datePickers = $(".datePicker");
	$datePickers
		.each(function() {
			// resize the input so that its width does not change after we add the calendar icon
			var iconWidth = 22;
			var inputWidth = $(this).css("width");
			if (inputWidth.indexOf('px') > 0) { // make sure it's in px
				inputWidth = parseInt(inputWidth);
			} else { // can't find width in css, try jQuery
				inputWidth = $(this).width();
			}
			if (inputWidth > iconWidth) {
				$(this).css({ width: (inputWidth-iconWidth)+"px" });
			}
		})
		.datepicker({
			buttonImage: icp.getBaseUrl('/static/images/icons/calendar.jpg'),
			buttonImageOnly: true,
			buttonText: 'Choose a date',
			changeMonth: true,
			changeYear: true,
			maxDate: '+1d',
			minDate: new Date(2003, 1 - 1, 1),
			showOn: 'button'
		});
	// some datePickers have a short year format
	$datePickers.filter('.shortYear')
		.datepicker('change', {
			dateFormat: 'mm/dd/y'
		});
	// some datepickers allow future dates
	$datePickers.filter('.future')
		.datepicker('option', 'maxDate', '+1y +1d');
	
	// For date ranges, update each element's 'sister' date when the other is set for the first time
	$(".dateFrom input").each(function(index) {
		this.sisterDateExpr = ".dateTo input:eq("+index+")";
	});
	$(".dateTo input").each(function(index) {
		this.sisterDateExpr = ".dateFrom input:eq("+index+")";
	});
	$(".dateFrom input,.dateTo input").change(function() {
		var enteredDate = $(this).attr("value");
		$(this.sisterDateExpr).each(function () {
			if (! $(this).attr("value")) { // only update if it's empty
				$(this).attr("value",enteredDate);
			}
		});
	});
	
	// set jQuery UI Dialog defaults
	$.extend(
		$.ui.dialog.defaults,
		{
			buttons: { 'Close': closeDialogLightbox },
			html: '',  // new property, for the markup to place inside the dialog body
			focus: function() {
				oldOverlayClickFunction = $('.ui-widget-overlay').click;
				$('.ui-widget-overlay').click(function() {
					closeDialogLightbox();
					$('.ui-widget-overlay').click(oldOverlayClickFunction);
				});
			},
			modal: true,
			title: ''
		}
	);
	
	// IE6 submits all buttons in a form, regardless of which is clicked
	// This disables any button that is not clicked so it will not be submitted
    var clickedButton;
    $('button').click(function() {
        clickedButton = this;
    });
    $('form').submit(function() {
        var buttons = $(this)
                .find('button:enabled')
                .not(clickedButton || "")
                .attr('disabled', 'disabled');
        setTimeout(function() {
            buttons.removeAttr('disabled');
        }, 1);
    });
	
}); // end document.ready



// warn users if they try to leave the page after making changes
icp.preventNavigation = {
	contentChanged: false,
	reset: function() {
		icp.preventNavigation.contentChanged = false;
		
		// capture the first change made on the page
		// we delay the event binding in case any document.ready code causes
		// a change event during initialization
		setTimeout(function() {
			// IE doesn't bubble change events, so we need to bind to individual
			// elements instead of the document
			$('input, textarea, select').bind('change.preventNavigation', function() {
				icp.preventNavigation.contentChanged = true;
				$('input, textarea, select').unbind('change.preventNavigation');
			});
			// find WYSIWYGPro editors
			$('textarea.wpHtmlEditArea').each(function() {
				var editorFrame = $('#' + this.name + '_editFrame')[0].contentWindow;
				$(editorFrame.document).one('keypress', function() {
					icp.preventNavigation.contentChanged = true;
				});
			});
		}, 1);
	}
};
$(document).ready(function() {
	var msg = $('meta[name=preventNavigation]').attr('content');
	
	if (!msg) {
		return;
	}
	
	icp.preventNavigation.reset();
	
	// allow specific links/buttons to navigate away without warning
	$('.allowNavigation').click(function() {
		icp.preventNavigation.contentChanged = false;
	});
	
	window.onbeforeunload = function() {
		if (icp.preventNavigation.contentChanged) {
			return msg;
		}
	};
});

})();



/**
 *  Used to create a lightbox via the jQuery UI Dialog. This should be used
 *  instead of our old Thickbox, going forward.
 * 
 *  @param dialogOptions   a hash of Dialog options to submit to the Dialog
 */
function openDialogLightbox(dialogOptions) {
	$dialogElement = $('.dialogLightbox');
	
	if ($dialogElement.length == 0) {
		// we require a dialogLightbox element on the page, before we can create the dialog
		$('body').append(
			'<div class="dialogLightbox"></div>'
		);
		$dialogElement = $('.dialogLightbox');
		$dialogElement.hide();
	}
	
	if (dialogOptions.html) {
		// special case: there is no property for the dialog's contents, so we fake one.
		$dialogElement.html(dialogOptions.html);
	}
	
	if ($dialogElement.dialog('isOpen')) {
		// to update an existing dialog, we have to set each option individually
		if (typeof(dialogOptions) == 'object') {
			for (prop in dialogOptions) {
				$dialogElement.dialog('option', prop, dialogOptions[prop]);
			}
		}
	} else {
		$dialogElement
			.dialog('destroy')       // dialog needs to be destroyed to clear out any resizing/repositioning
			.dialog(dialogOptions);
	}
	return $dialogElement;
}


/**
 *  Closes a lightbox based on the jQuery UI Dialog. This should be used
 *  instead of our old Thickbox, going forward.
 */
function closeDialogLightbox() {
	// we don't just close it, we destroy it -- to clear out any resizing/repositioning
	$('.dialogLightbox')
		.dialog('close')
		.dialog('destroy');
}


function openWin() {
	var w = 300,
		h = 400,
		winTop = Math.round((screen.height / 2) - (h / 2)),
		winLeft = Math.round((screen.width / 2) - (w / 2));
	
	window.open("","popup","top="+winTop+",left="+winLeft+",width="+w+",height="+h+",scrollbars=yes,resize=yes,resizable=yes,menubar=yes,scrollbars,toolbar,toolbar=yes");
}

function openWinVar(w,h,url) {
	var winTop = Math.round((screen.height / 2) - (h / 2)),
		winLeft = Math.round((screen.width / 2) - (w / 2));
	
	window.open(url,"winvar","top="+winTop+",left="+winLeft+",width="+w+",height="+h+",scrollbars=yes,resize=yes,resizable=yes,menubar=yes,scrollbars,toolbar,toolbar=yes");
}

function openPlainWinVar(w,h,url) {
	var winTop = Math.round((screen.height / 2) - (h / 2)),
		winLeft = Math.round((screen.width / 2) - (w / 2));
	
	window.open(url,"winvar","top="+winTop+",left="+winLeft+",width="+w+",height="+h+",location=no,scrollbars=no,resize=no,resizable=yes,menubar=no,toolbars=no,statusbar=no");
}


function ConfirmDelete(pName, pRedirect) {
	pName = pName || "Untitled";
	if (confirm("Are you sure you would like to delete "+ pName +"?")) {
		window.location.href = pRedirect;
	}
}

function ConfirmDeleteForPost(pName) {
	pName = pName || "Untitled";
	return confirm("Are you sure you would like to delete "+ pName +"?");
}

function htmlPreview(htmlArea) {
	var win = window.open(", ", 'popup', 'toolbars=no,status=no,scrollbars=yes,resizable=yes');
	win.document.write("" + htmlArea);
	win.document.close();
}

function spamCheckPreview(htmlArea) {
	var win = window.open(", ", 'popup', 'width=580,height=325,toolbars=no,status=no,scrollbars=yes,resizable=yes');
	win.document.write("" + htmlArea);
	win.document.close();
}

function nothing() {
	// This function is for null links so that 
	// icons can be used in the existing format
	// without requiring links.  Do not delete.	
}

// Returns html from WysiwygPro and refreshes the editor
function getWysiwygCode(editor) {
    var htmlcode = editor.getCode();
    editor.updateWysiwyg();
    return htmlcode;
}

function sleuth() {
	if (document.cookie.indexOf("__utmz=") != -1) {
		var z = readCookie('__utmz'),
			za = z.split('|'),
			t = za[0].split('.');
		za[0] = t[t.length - 1];
		
		for (i = 0; i < za.length; i++) {	
			t2 = za[i].split('=');
			if (t2[0] == 'utmgclid' || t2[1] == 'cpc' || t2[1] == 'ppc') {
				getRef();
			}
		}
	}
	
	function readCookie(name) {
		var nameEQ = name + "=",
			ca = document.cookie.split(';');
		
		for (var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0) == ' ') { c = c.substring(1, c.length); }
			if (c.indexOf(nameEQ) === 0) {
				return c.substring(nameEQ.length, c.length);
			}
		}
		return null;
	}
	
	function getRef() {
		var ref = document.referrer,
			re = /(\?|&)(q|p)=([^&]*)/,
			searchq = re.exec(ref);
		
		if (searchq) {
			__utmSetVar(searchq[3]);
		}
	}
}


/**
 * Script to notify user near the end of their session
 *  - works with both client keepalive ping on or off
 */
$(document).ready(function() {
	//TODO: use jquery to do this
	function getReadableLogoutTime(dTime) {
		var iHours = dTime.getHours(),
			sMinutes = dTime.getMinutes().toString(),
			sAmPm = 'am',
			sDay = dTime.getDate(),
			sMonth = dTime.getMonth() + 1,
			sYear = dTime.getFullYear();
		
		if (dTime.getHours() >= 11) {
			sAmPm = 'pm';
		}
		
		if (iHours > 11) {
			iHours -= 12;
		}
		iHours = iHours == 0 ? 12 : iHours;
		
		if(sMinutes.length == 1) {
			sMinutes = '0' + sMinutes;
		}
		//TODO: localize this time format (or make more locale neutral)
		return iHours + ':' + sMinutes + ' ' + sAmPm +' on ' + sMonth + '/' + sDay + '/' + sYear;
	}
	
	var iStartTime = icp.now(),
		iLastSuccessfulPingTime = iStartTime,
		oTimeouts = icp.getTimeouts(),
		
		iServerTimeout = oTimeouts.iServerTimeout, 
		iClientTimeout = oTimeouts.iClientTimeout,
		iNotificationMultiplier = oTimeouts.iNotificationMultiplier,
		
		iPingInterval = iServerTimeout * 0.75,
		iRetryInterval = iServerTimeout * 0.25 * 0.25, 
		//TODO: calculate iOffset in icp.init after fixing 'now()' context
		iOffset = oTimeouts.iServerTime - icp.now(), //just in case user's clock is way off
		
		iPingTimeoutId,
		
		$document = $(document);
	
	//is client ping enabled?
	if (icp.getTimeouts().iClientTimeout) {
		//ping the server every so often to keep the session alive as long
		//as the user has a browser window open		

	
		function timeSinceStart() {
			return icp.now() - iStartTime + iOffset;
		}
		
		function timeSincePing() {
			return icp.now() - iLastSuccessfulPingTime + iOffset;
		}
		
		function pingSuccess(aFromServer) {
			iStartTime = aFromServer.iStartTime; 
			iLastSuccessfulPingTime = icp.now();
	
			if (iStartTime == 0) {
				//user is logged out
				//are we supposed to notify the user?
				if (iNotificationMultiplier > 0) {
					$document.trigger('keepalive.loggedout');
				}
			} else if (timeSinceStart() < iClientTimeout - iServerTimeout) { 
				//normal ping
				clearTimeout(iPingTimeoutId); //we should never have more than one keepalive ping waiting
				$document.trigger('keepalive.ping', iPingInterval);
			} else { 
				//last ping (should hit after session timeout unless user does something)
				clearTimeout(iPingTimeoutId); //we should never have more than one keepalive ping waiting
				$document.trigger('keepalive.ping', iServerTimeout * 1.1);
			}
		}
	
		$document
			.bind('keepalive.ping', function(event, iDelay) {
				iPingTimeoutId = setTimeout(function() {
					icp.ajax(icp.getCoreUrl('/keepalive'), {}, {
						success: pingSuccess,
						error: function() {
							//assume we timeout if we have passed iServerTimeout & haven't connected
							if (timeSincePing() <= iServerTimeout) {
								$document.trigger('keepalive.ping', iRetryInterval);
							}
						},
						complete: function () {
							//if iNotificationMultiplier is <= 0, don't notify the user (feature is turned off)
							//don't ping user if session is already timed out (iStartTime == 0)
							if (iNotificationMultiplier > 0
									&& iStartTime != 0
									&& timeSinceStart() > iClientTimeout * iNotificationMultiplier) {
								$document.trigger('keepalive.userpoke');
							}
						}
					});
				}, iDelay);
			})
			.bind('keepalive.resetping', function() {
				icp.ajax(icp.getCoreUrl('/keepalive/reset'), {}, {
					success: pingSuccess,
					error: function() {
						if (timeSincePing() <= iServerTimeout) {
							//TODO: pop up 'error pinging' dialog
							$document.trigger('keepalive.resetping', 60000);
						}
					}
				});
			})
			.bind('keepalive.userpoke', function() {
				var dialog = $("#keepaliveUserPoke");
				$('#loggedOutTime').html(getReadableLogoutTime(new Date(iStartTime + iClientTimeout + iOffset)));
				openDialogLightbox({
					title: dialog.attr("title"), 
					html: dialog.html(),
					close: function() {
							$document.trigger('keepalive.resetping');
						},
					buttons: { "I'm here": closeDialogLightbox} //TODO: create templating system for buttons
				}); //end openDialogLightbox
			})
			.bind('keepalive.loggedout', function() {
				var dialog = $("#keepaliveloggedout");
				openDialogLightbox({
					title: dialog.attr("title"), 
					html: dialog.html(),
					close: null,
					buttons: {}
				});
			})
			.trigger('keepalive.ping', iPingInterval);
		// end client ping is enabled
	} else if (iNotificationMultiplier > 0) {
		//notify near end of server side session
		
		function getPokeDelay() {
			return iServerTimeout * iNotificationMultiplier;
		}
		
		$document
			.bind('keepalive.userPoke', function(event, iDelay) {
				iPingTimeoutId = setTimeout( function() {
					var dialog = $("#keepaliveUserPoke");
					$('#loggedOutTime').html(getReadableLogoutTime(new Date(iStartTime + iServerTimeout + iOffset)));
					openDialogLightbox({
						title: dialog.attr("title"), 
						html: dialog.html(),
						close: function() {
								$document.trigger('keepalive.resetping');
							},
						buttons: { "I'm here": closeDialogLightbox} //TODO: create templating system for buttons
					}); //end openDialogLightbox
				}, iDelay);
			})
			.bind('keepalive.loggedout', function() {
				var dialog = $("#keepaliveloggedout");
				openDialogLightbox({
					title: dialog.attr("title"), 
					html: dialog.html(),
					buttons: {}
				});
			})
			.bind('keepalive.resetping', function() {
				icp.ajax(icp.getCoreUrl('/keepalive/reset'), {}, {
					success: function(aFromServer) {
						iStartTime = aFromServer.iStartTime; 
						if (iStartTime != 0) {
							clearTimeout(iPingTimeoutId);
							$document.trigger('keepalive.userPoke', getPokeDelay());
						} else {
							$document.trigger('keepalive.loggedout');
						}
					},
					error: function() {
						//TODO: show error dialog
						$document.trigger('keepalive.resetping', 60000);
					}
				});
			})
			.trigger('keepalive.userPoke', getPokeDelay());	
		
	} // end icp.getTimeouts.iClientTimeout
}); //end document.ready
 
//handles death clock and system messages
$(document).ready(function() {
	
	var cookieName = 'clock_dismissed',
		aIds = $.cookie(cookieName) ? $.cookie(cookieName).split('.') : [];
	
	$('<img class="closeSystemEvent" src="' + icp.getBaseIncludeUrl('/images/icons/close_16.png') + '"/>')
		.click(function() {
			var dismissed = $(this).parent().hide();
			aIds.push(dismissed.attr('id'));
			$.cookie(cookieName, aIds.join('.'), {path: '/', expires: 30});
		})
		.prependTo('.systemEvent');

	$('.notificationMessageBox').find('.closeButton').click(function(){
		var id = $(this).closest('.notificationMessageBox').slideUp().attr('id');
		$.cookie(id.substring(11), 1, {
			path: '/',
			expires: 365
		});
	});
});

(function($) {
	var viewportMessages = {
		container: null,
		delay: 12000,
		fadeDuration: 3000,
		slideDuration: 500,
		
		init: function() {
			viewportMessages.container = $('<div></div>')
				.attr('id', 'viewportMessages')
				.appendTo('body');
			
			if (viewportMessages.container.css('position') !== 'fixed') {
				$(window).bind('scroll', function() {
					viewportMessages.container.stop(true).animate({
						top: $(window).scrollTop()
					}, 200);
				});

				//manually animate down once incase the user is scrolled when the message instantiated
				viewportMessages.container.stop(true).animate({
					top: $(window).scrollTop()
				}, 200);
			}
			
			viewportMessages.init = function() {};
		},
		
		_createMessage: function(message) {
			return $('<div><div></div></div>')
				.addClass('messageContainer')
				.children()
					.addClass('message')
					.html(message)
				.end()
				.prependTo(viewportMessages.container);
		},
		
		showTemporaryMessage: function(message) {
			viewportMessages.init();
			var elem = viewportMessages._createMessage(message).children()
					.addClass('temporaryMessage').end();

			elem.effect("highlight", {color: "#000"}, 1000)
				.children().effect("highlight", {color: "#fff"}, 3000);
			
			setTimeout(function() {
				elem
					.fadeTo(viewportMessages.fadeDuration, 0)
					.slideUp(viewportMessages.slideDuration, function() {
						$(this).remove();
					});
			}, viewportMessages.delay);
		},
		
		showPersistentMessage: function(message) {
			viewportMessages.init();
			var elem = viewportMessages._createMessage(message).children()
					.addClass('persistentMessage').end(),
				
				button = $('<button></button>')
					.addClass('closeButton')
					.click(function() {
						elem.animate({
							opacity: 0,
							height: 0
						}, viewportMessages.slideDuration, function() {
							$(this).remove();
						});
					})
					.prependTo(elem.children()),
				
				buttonText = $('<span></span>')
					.text('close')
					.appendTo(button);
			
			elem.effect("highlight", {color: "#000"}, 1000)
				.children().effect("highlight", {color: "#fff"}, 3000);
		}
	};
	
	icp.temporaryMessage = viewportMessages.showTemporaryMessage;
	icp.persistentMessage = viewportMessages.showPersistentMessage;
})(jQuery);

$(document).ready(function() {
	if ($.fn.colorPicker) {
		$('.colorPicker input').colorPicker();
		$('#color_selector').bgiframe();
	}
});
