jQuery(document).ready(function($) {
	var $cal_fields = $('#calendar_fields');
	
	// I'm overriding this method from JQ UI because it's acting
	// strangely. Note the changes in the return value.
	$.datepicker._isInRange = function(inst, date) {
		// during range selection, use minimum of selected date and range start
		var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
			new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
		newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
		var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
		var maxDate = this._getMinMaxDate(inst, 'max');
// Solspace
		//return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
		return ((!minDate || date.getTime() >= minDate.getTime()) && (!maxDate || date.getTime() <= maxDate.getTime()));
	};
	
	// Overriding this method for the same reason.
	$.datepicker._generateHTML = function(inst) {
		var today = new Date();
		today = this._daylightSavingAdjust(
			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
		var isRTL = this._get(inst, 'isRTL');
		var showButtonPanel = this._get(inst, 'showButtonPanel');
		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
		var numMonths = this._getNumberOfMonths(inst);
		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
		var stepMonths = this._get(inst, 'stepMonths');
		var stepBigMonths = this._get(inst, 'stepBigMonths');
		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
		var minDate = this._getMinMaxDate(inst, 'min', true);
		var maxDate = this._getMinMaxDate(inst, 'max');
		var drawMonth = inst.drawMonth - showCurrentAtPos;
		var drawYear = inst.drawYear;
		if (drawMonth < 0) {
			drawMonth += 12;
			drawYear--;
		}
		if (maxDate) {
			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
				maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
				drawMonth--;
				if (drawMonth < 0) {
					drawMonth = 11;
					drawYear--;
				}
			}
		}
		inst.drawMonth = drawMonth;
		inst.drawYear = drawYear;
		var prevText = this._get(inst, 'prevText');
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
			this._getFormatConfig(inst)));
		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
		var nextText = this._get(inst, 'nextText');
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
			this._getFormatConfig(inst)));
		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
		var currentText = this._get(inst, 'currentText');
		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
		currentText = (!navigationAsDateFormat ? currentText :
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
		firstDay = (isNaN(firstDay) ? 0 : firstDay);
		var dayNames = this._get(inst, 'dayNames');
		var dayNamesShort = this._get(inst, 'dayNamesShort');
		var dayNamesMin = this._get(inst, 'dayNamesMin');
		var monthNames = this._get(inst, 'monthNames');
		var monthNamesShort = this._get(inst, 'monthNamesShort');
		var beforeShowDay = this._get(inst, 'beforeShowDay');
		var showOtherMonths = this._get(inst, 'showOtherMonths');
		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
		var endDate = inst.endDay ? this._daylightSavingAdjust(
			new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
		var defaultDate = this._getDefaultDate(inst);
		var html = '';
		for (var row = 0; row < numMonths[0]; row++) {
			var group = '';
			for (var col = 0; col < numMonths[1]; col++) {
				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
				var cornerClass = ' ui-corner-all';
				var calender = '';
				if (isMultiMonth) {
					calender += '<div class="ui-datepicker-group ui-datepicker-group-';
					switch (col) {
						case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
						case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
						default: calender += 'middle'; cornerClass = ''; break;
					}
					calender += '">';
				}
				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
					selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
					'</div><table class="ui-datepicker-calendar"><thead>' +
					'<tr>';
				var thead = '';
				for (var dow = 0; dow < 7; dow++) { // days of the week
					var day = (dow + firstDay) % 7;
					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
				}
				calender += thead + '</tr></thead><tbody>';
				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
					calender += '<tr>';
					var tbody = '';
					for (var dow = 0; dow < 7; dow++) { // create date picker days
						var daySettings = (beforeShowDay ?
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
						var otherMonth = (printDate.getMonth() != drawMonth);
//Solspace
						var unselectable = otherMonth || !daySettings[0] ||
							(minDate && printDate.getTime() < minDate.getTime()) || (maxDate && printDate.getTime() > maxDate.getTime());
						//var unselectable = otherMonth || !daySettings[0] ||
							//(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
						tbody += '<td class="' +
							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
							// or defaultDate is current printedDate and defaultDate is selectedDate
							' ' + this._dayOverClass : '') + // highlight selected day
							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
							(printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
							' ' + this._currentClass : '') + // highlight selected day
							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
							(unselectable ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
							inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
							(otherMonth ? (showOtherMonths ? printDate.getDate() : '&#xa0;') : // display for other months
							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
							(printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
							' ui-state-active' : '') + // highlight selected day
							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
						printDate.setDate(printDate.getDate() + 1);
						printDate = this._daylightSavingAdjust(printDate);
					}
					calender += tbody + '</tr>';
				}
				drawMonth++;
				if (drawMonth > 11) {
					drawMonth = 0;
					drawYear++;
				}
				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
				group += calender;
			}
			html += group;
		}
		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
		inst._keyEvent = false;
		return html;
	};
	
	var initialize = function() {
		// Publish/edit form
		if ($('.publishRows').length > 0) {
			// Place the calendar fields at the top of the publish form
			if ($('.publishRows').length > 1) {
				$('.publishRows:eq(0)').before($cal_fields);
			}
			
			// Add the timezone menu, if appropriate
			$tz = $('#calendar_timezone_menu');
			if ($tz.length > 0) {
				var $tz_field = $('#'+$tz.attr('title'));
				if ($tz_field.length > 0) {
					$tz_field.replaceWith($tz.find('select').attr('id', $tz.attr('title')).attr('name', $tz.attr('title')));
					$tz.remove();
				}
			}
			
			// Add the default time format, if appropriate
			$tf = $('#calendar_time_format');
			if ($tf.length > 0) {
				var $tf_field = $('#'+$tf.attr('title'));
				if ($tf_field.length > 0) {
					$tf_field.val($tf.text());
					$tf.remove();
				}
			}
			
			// Toggle display of details based on whether a calendar is selected
			toggle_event_details();
			
			// Set the default From and To dates
			set_default_dates();
			
			// Deactivate time fields for all day events
			toggle_time_fields($('div.all_day input:checkbox', $cal_fields));
			
			// Toggle monthly by
			toggle_monthly_by();
			
			// Add date picker to first From field
			$('div.first input[name=start_date]', $cal_fields).datepicker({
				dateFormat: SSCalendar.dateFormat,
				dayNames: SSCalendar.dateFormatSettings.dayNames,
				dayNamesShort: SSCalendar.dateFormatSettings.dayNamesShort,
				dayNamesMin: SSCalendar.dateFormatSettings.dayNamesMin,
				monthNames: SSCalendar.dateFormatSettings.monthNames,
				monthNamesShort: SSCalendar.dateFormatSettings.monthNamesShort,
				changeMonth: true,
				changeYear: true,
				onSelect: function() {
					update_from_field_mindate($('div.rule:not(.first)', $cal_fields));
					update_to_field_mindate($('div.first', $cal_fields), true);
					update_end_by_mindate($('div.rule', $cal_fields));
					update_picker_three_mindate($('div.rule', $cal_fields));
				}
			});
			
			// Add date picker to first To field
			$('div.first input[name=end_date]', $cal_fields).datepicker({
				dateFormat: SSCalendar.dateFormat,
				dayNames: SSCalendar.dateFormatSettings.dayNames,
				dayNamesShort: SSCalendar.dateFormatSettings.dayNamesShort,
				dayNamesMin: SSCalendar.dateFormatSettings.dayNamesMin,
				monthNames: SSCalendar.dateFormatSettings.monthNames,
				monthNamesShort: SSCalendar.dateFormatSettings.monthNamesShort,
				changeMonth: true,
				changeYear: true
			});
			update_to_field_mindate($('div.first', $cal_fields), false);
			
			// Add date picker to other From fields
			$('div.rule:not(.first) input[name=start_date]', $cal_fields).datepicker({
				dateFormat: SSCalendar.dateFormat,
				dayNames: SSCalendar.dateFormatSettings.dayNames,
				dayNamesShort: SSCalendar.dateFormatSettings.dayNamesShort,
				dayNamesMin: SSCalendar.dateFormatSettings.dayNamesMin,
				monthNames: SSCalendar.dateFormatSettings.monthNames,
				monthNamesShort: SSCalendar.dateFormatSettings.monthNamesShort,
				changeMonth: true,
				changeYear: true,
				onSelect: function() {
					$mama = $(this).closest('.rule');
					update_to_field_mindate($mama, false);
					update_end_by_mindate($mama);
					update_picker_three_mindate($mama);
				}
			});
			
			// Add date picker to other To fields
			$('div.rule:not(.first) input[name=end_date]', $cal_fields).datepicker({
				dateFormat: SSCalendar.dateFormat,
				dayNames: SSCalendar.dateFormatSettings.dayNames,
				dayNamesShort: SSCalendar.dateFormatSettings.dayNamesShort,
				dayNamesMin: SSCalendar.dateFormatSettings.dayNamesMin,
				monthNames: SSCalendar.dateFormatSettings.monthNames,
				monthNamesShort: SSCalendar.dateFormatSettings.monthNamesShort,
				changeMonth: true,
				changeYear: true
			}).each(function() {
				update_to_field_mindate($(this).closest('.rule'), false);
			});
			
			// Create select_dates picker
			create_select_dates_picker();
			
			// Create selector widgets
			create_selector_widget($('select.selector', $cal_fields));
			
			// Toggle end by
			toggle_end_by();
			$('input[name=end_by_date]').datepicker({
				dateFormat: SSCalendar.dateFormat,
				dayNames: SSCalendar.dateFormatSettings.dayNames,
				dayNamesShort: SSCalendar.dateFormatSettings.dayNamesShort,
				dayNamesMin: SSCalendar.dateFormatSettings.dayNamesMin,
				monthNames: SSCalendar.dateFormatSettings.monthNames,
				monthNamesShort: SSCalendar.dateFormatSettings.monthNamesShort,
				changeMonth: true,
				changeYear: true
			});
			update_end_by_mindate($('div.rule', $cal_fields));
			
			// Format dates that are in YYYYMMDD format
			$('input.picker', $cal_fields).each(function() {
				var val = $(this).val();
				$(this).val($.datepicker.formatDate(SSCalendar.dateFormat, _get_date(val), SSCalendar.dateFormatSettings));
			});
			
			show_hide_x();
		}
		// Calendar Module control panel
		else if ($('#contentNB').length > 0) {
			// Add date picker to relevant fields
			$('input.picker').datepicker({
				dateFormat: SSCalendar.dateFormat,
				dayNames: SSCalendar.dateFormatSettings.dayNames,
				dayNamesShort: SSCalendar.dateFormatSettings.dayNamesShort,
				dayNamesMin: SSCalendar.dateFormatSettings.dayNamesMin,
				monthNames: SSCalendar.dateFormatSettings.monthNames,
				monthNamesShort: SSCalendar.dateFormatSettings.monthNamesShort,
				changeMonth: true,
				changeYear: true,
				yearRange: '1900:2050'
			});
		}
	};
	
	var create_select_dates_picker = function($context) {
		if ($context == undefined) {
			$context = $cal_fields;
		}
		
		// Add date picker
		$('.picker_three', $context).each(function() {
			var $this = $(this);
			$this.closest('.rule').find('.date_range .date input').datepicker('destroy').remove().end().find('.date_range .time label').remove();
			
			var data = new Array;
			$this.children('span.date').each(function() {
				data.push($.datepicker.formatDate(SSCalendar.dateFormat, _get_date($(this).text()), SSCalendar.dateFormatSettings));
			}).hide().end();
			$this.data('values', data);
			var startDate = ($this.data('values')[0]) ? $this.data('values')[0] : '';
			
			$this.datepicker({
				numberOfMonths: 2,
				showButtonPanel: true,
				changeMonth: true,
				changeYear: true,
				dateFormat: SSCalendar.dateFormat,
				dayNames: SSCalendar.dateFormatSettings.dayNames,
				dayNamesShort: SSCalendar.dateFormatSettings.dayNamesShort,
				dayNamesMin: SSCalendar.dateFormatSettings.dayNamesMin,
				monthNames: SSCalendar.dateFormatSettings.monthNames,
				monthNamesShort: SSCalendar.dateFormatSettings.monthNamesShort,
				onSelect: function(dateText, inst){
					//var $p3 = $(this).find('.ui-datepicker-current-day').closest('.picker_three');
					var data = $this.data('values');
					var index = $.inArray(dateText, data);
					if (index > -1) {
						data.splice(index, 1);
					} else {
						data.push(dateText);
					}
					$this.data('values', data);
					},
				beforeShowDay: function(date) {
					var array = new Array;
					array[0] = true;
					array[1] = '';
					array[2] = '';
					if ($.inArray($.datepicker.formatDate(SSCalendar.dateFormat, date, SSCalendar.dateFormatSettings), $this.data('values')) > -1) {
						array[1] = 'ui-datepicker-selected-day';
					}
					return array;
				}
			});
			
			$this.datepicker('setDate', _get_date(startDate));
			if ($('#calendar_wrapper .rule.first input[repeat_select]').val() == 'select_dates') {
				$this.datepicker('option', 'minDate', _get_date($('#calendar_wrapper .rule.first input[name=start_date]').val()));
			}
			
		});
		
		//update_picker_three_mindate($context);
	};
	
	var set_default_dates = function() {
		var $rule = $(get_rule(1));
		if ($rule.length == 0) return;
		var ee_date = get_ee_date();
		var $from_date = $rule.find('input[name=start_date]');
		var $to_date = $rule.find('input[name=end_date]');
		
		/*
		if ($from_date.val() == '') {
			$from_date.val(ee_date);
		}
		
		if ($to_date.val() == '') {
			$to_date.val(ee_date);
		}
		*/
	};
	
	var get_rule = function(which) {
		var $rule = $('.rule', $cal_fields);
		if ($rule[which-1] !== 'undefined') {
			return $rule[which-1];
		}
		return false;
	};
	
	var get_ee_date = function() {
		var date = $('#entry_date').val();
		
		if (date != undefined) {
			date = date.substring(0, 10).split('-');
			date = $.datepicker.formatDate(SSCalendar.dateFormat, new Date(date[0], date[1] - 1, date[2]), SSCalendar.dateFormatSettings);
		} else {
			date = $.datepicker.formatDate(SSCalendar.dateFormat, new Date(), SSCalendar.dateFormatSettings);
		}
		return date;
	};
	
	var toggle_time_fields = function($fields) {
		$fields.each(function() {
			var $rule = $(this).closest('.rule');
			
			if ($rule.find('select[name=type]').val() != '-') {
				$rule.find('.date_range, .date_range *').removeClass('inactive')
			}
			
			if ($(this).is(':checked')) {
				// Is "Select Dates" selected?
				if ($rule.find('select[name=interval]').val() == 'select_dates') {
					$rule.find('.date_range div.time, .date_range div.date').addClass('inactive').end().find('.all_day input[type=checkbox]').attr('checked', 'checked');
				} else {
					$(this).closest('.date_range').find('.time').addClass('inactive').end().find('.all_day input[type=checkbox]').attr('checked', 'checked');
				}
			}
		})
	};
	
	var update_from_field_mindate = function($context) {
		if ($context.length == 0) return;
		
		var global_start_date = new Date($('div.first input[name=start_date]', $cal_fields).val());
		var local_start_date = $('div.date_range input[name=start_date]:eq(0)', $context).val();
		if (local_start_date != '') {
			local_start_date = new Date(local_start_date);
		} else {
			local_start_date = global_start_date;
		}
		$('div.date_range input[name=start_date]:eq(0)', $context).datepicker('option', 'minDate', global_start_date);
		if (local_start_date == 0 || local_start_date <= global_start_date) {
			$('div.date_range input[name=start_date]:eq(0)', $context).val($.datepicker.formatDate(SSCalendar.dateFormat, global_start_date, SSCalendar.dateFormatSettings));
			update_to_field_mindate($context, true);
			update_picker_three_mindate($context);
			update_end_by_mindate($context);
		}
	};
	
	var update_to_field_mindate = function($context, adjustToStartValue) {
		if ($context.length == 0) return;
		
		var $end = $('div.date_range input[name=end_date]:eq(0)', $context);
		var start_val = String($('div.date_range input[name=start_date]:eq(0)', $context).val());
		var end_val = String($end.val());
		
		var start_date = _get_date(start_val);
		var end_date = _get_date(end_val);
		
		$end.datepicker('option', 'minDate', start_date);
		if (end_date < start_date || (adjustToStartValue && end_date > start_date)) {
			$end.val($.datepicker.formatDate(SSCalendar.dateFormat, start_date, SSCalendar.dateFormatSettings));
		} else {
			$end.val($.datepicker.formatDate(SSCalendar.dateFormat, end_date, SSCalendar.dateFormatSettings));
		}
	};
	
	var update_end_by_mindate = function($context) {
		var $eb = $context.find('.end input[name=end_by_date]');
		$eb.each(function() {
			$(this).datepicker('setDate', _get_date($(this).val()));
			var $start_date = $(this).closest('.rule').find('input[name=start_date]');
			$(this).datepicker('option', 'minDate', _get_date($start_date.val()));
			if ($(this).datepicker('getDate') == null || $(this).datepicker('getDate') < $start_date.datepicker('getDate'))
			{
				$(this).datepicker('setDate', $start_date.datepicker('getDate'));
			}
			$.datepicker._refreshDatepicker($(this));
		});
	};
	
	var update_picker_three_mindate = function($context) {
		var $p3 = $('.picker_three', $context);
		$p3.each(function() {
			$(this).datepicker('option', 'minDate', _get_date($(this).closest('.rule').find('input[name=start_date]').val()));
			$.datepicker._refreshDatepicker($(this));
		});
	};
	
	var _get_date = function(val) {
		if (val == undefined) {
			return new Date();
		}
		if (parseInt(val) == val && String(val).length == 8) {
			return $.datepicker.parseDate('yymmdd', val, SSCalendar.dateFormatSettings);
		} else {
			return $.datepicker.parseDate(SSCalendar.dateFormat, val, SSCalendar.dateFormatSettings);
		}
	};
	
	var toggle_event_details = function() {
		if ($('#calendar_calendars select[name=calendar_calendar_id]', $cal_fields).val() != '') {
			$('#calendar_new_date, div.rule', $cal_fields).show();
		} else {
			$('#calendar_new_date, div.rule', $cal_fields).hide();
		}
	};
	
	var toggle_selector_item = function($item) {
		if ($item.hasClass('close')) {
			reset_selector_widget($item.closest('.selector'));
		} else {
			if ($item.data('selector') == true) {
				$item.removeData('selector').find('a').removeClass('selected');
			}
			else {
				$item.data('selector', true).find('a').addClass('selected');
			}
			update_selector_widget($item.closest('.selector'));
		}
	};
	
	var update_selector_widget = function($selector) {
		$selector.removeData('selector')
		var data = new Array;
		$selector.find('.item').each(function() {
			if ($(this).data('selector') == true && $(this).data('value') != undefined) {
				data.push($(this).data('value'));
			}
		});
		$selector.data('selector', data);
	};
	
	var create_selector_widget = function($selectors) {
		$selectors.each(function() {
			var $div = $("<div class='selector line'></div>");
			var items = new Array;
			var count = 1;
			$(this).find('option').each(function() {
				var text = $(this).text();
				var selected = ($(this).is(':selected')) ? true : false;
				var d_class = (count % 7 == 1) ? " newline" : '';
				var s_class = (selected == true) ? " class='selected'" : '';
				items.push($("<div class='item"+d_class+"'><a href='#'"+s_class+">"+text+"</a></div>").data('value', $(this).val()).data('selector', selected));
				count ++;
			});
			if (items.length > 0) {
				items.push("<div class='item close'><a href='#'>X</a></div>");
			}
			$.each(items, function(k, item) {
				$div.append(item);
			});
			$(this).replaceWith($div);
		});
	};
	
	var reset_selector_widget = function($selector) {
		$selector.removeData('selector').find('.item').each(function() {
			$(this).removeData('selector').find('a').removeClass('selected');
		})
	};
	
	var toggle_interval_details = function($select) {
		$select.each(function() {
			var output = {options: '', extra: ''};
		
			$(this).closest('.repeat_select').siblings('.options').remove().end().closest('.repeat').siblings('.end').remove().end().find('br.clear').remove().end().find('.picker_three').remove();
			
			switch($(this).val()) {
				case 'daily' :
					output = _html_repeat_interval_daily();
					restore_date_fields($(this));
					break;
				case 'weekly' :
					output = _html_repeat_interval_weekly();
					restore_date_fields($(this));
					break;
				case 'monthly' :
					output = _html_repeat_interval_monthly();
					restore_date_fields($(this));
					break;
				case 'yearly' :
					output = _html_repeat_interval_yearly();
					restore_date_fields($(this));
					break;
				case 'select_dates' :
					output = _html_repeat_interval_dates();
					// Discard From and To date fields
					$(this).closest('.rule:not(.first)').find('.date_range .date input').datepicker('destroy').remove().end().find('.date_range .time label').remove();
					break;
				default :
					restore_date_fields($(this));
					$rule = $(this).closest('.rule');
					if (_get_rule_type($rule) == '+' && _get_rule_all_day($rule) == '') {
						toggle_time_fields($(this));
					}
					break;
			};
			
			$(this).closest('.repeat_select').after(output.options).closest('.repeat').after(output.extra);
			initialize_interval_details($(this).closest('.rule'));
		});
	};
	
	var _html_repeat_interval_daily = function() {
		var output = {
			options: '<div class="options"><label>Every</label><input type="text" name="every" value="1" /> day(s).</div><br class="clear" />',
			extra: '<div class="group end line"><div class="leader"><label>End</label><select name="end"><option value="never">Never</option><option value="by_date">by Date</option><option value="after">After</option></select></div><br class="clear" /></div>'
		};
		return output;
	};
	
	var _html_repeat_interval_weekly = function() {
		var output = {
			options: '<div class="options"><label>Every</label><input type="text" name="every" value="1" /> week(s) on:<div class="extended line dows"><select class="selector" multiple="multiple"><option value="U">Sun</option><option value="M">Mon</option><option value="T">Tue</option><option value="W">Wed</option><option value="R">Thu</option><option value="F">Fri</option><option value="S">Sat</option></select></div><br class="clear" /></div><br class="clear" />',
			extra: '<div class="group end line"><div class="leader"><label>End</label><select name="end"><option value="never">Never</option><option value="by_date">by Date</option><option value="after">After</option></select></div><br class="clear" /></div>'
		};
		return output;
	};
	
	var _html_repeat_interval_monthly = function() {
		var output = {
			options: '<div class="options"><div class="every"><label>Every</label><input type="text" name="every" value="1" /> <label>month(s) by day of</label> <select name="by"><option value="by_date">month</option><option value="by_relative">week</option></select></div><div class="extended by_relative"><select class="selector" multiple="multiple"><option value="1">1st</option><option value="2">2nd</option><option value="3">3rd</option><option value="4">4th</option><option value="5">5th</option><option value="6">Last</option></select><br class="clear" /></div><div class="extended by_date"><select class="selector" multiple="multiple"><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="A">10</option><option value="B">11</option><option value="C">12</option><option value="D">13</option><option value="E">14</option><option value="F">15</option><option value="G">16</option><option value="H">17</option><option value="I">18</option><option value="J">19</option><option value="K">20</option><option value="L">21</option><option value="M">22</option><option value="N">23</option><option value="O">24</option><option value="P">25</option><option value="Q">26</option><option value="R">27</option><option value="S">28</option><option value="T">29</option><option value="U">30</option><option value="V">31</option></select><p class="clear">Only on:</p></div><div class="extended line dows"><select class="selector" multiple="multiple"><option value="U">Sun</option><option value="M">Mon</option><option value="T">Tue</option><option value="W">Wed</option><option value="R">Thu</option><option value="F">Fri</option><option value="S">Sat</option></select><br class="clear" /></div></div><br class="clear" />',
			extra: '<div class="group end line"><div class="leader"><label>End</label><select name="end"><option value="never">Never</option><option value="by_date">by Date</option><option value="after">After</option></select></div><br class="clear" /></div>'
		};
		return output;
	};
	
	var _html_repeat_interval_yearly = function() {
		var output = {
			options: '<div class="options"><label>Every</label><input type="text" name="every" value="1" /> year(s).</div><br class="clear" />',
			extra: '<div class="group end line"><div class="leader"><label>End</label><select name="end"><option value="never">Never</option><option value="by_date">by Date</option><option value="after">After</option></select></div><br class="clear" /></div>'
		};
		return output;
	};
	
	var _html_repeat_interval_dates = function() {
		var output = {
			options: '<div class="options"><div class="picker_three"></div></div>',
			extra: ''
		};
		return output;
	};
	
	var _html_end_by_date = function() {
		var output = '<div class="options"><input type="text" name="end_by_date" /></div>';
		return output;
	};
	
	var _html_end_after = function() {
		var output = '<div class="options"><input type="text" name="end_after" /> time(s)</div>';
		return output;
	};
	
	var _html_new_rule = function() {
		var output = '<div class="rule"><div class="inner"><div class="rule_number"><span></span></div><div class="rule_close"><a href="#">X</a></div><div class="group first type line"><div class="leader"><label>Type</label><select name="type"><option value="+">Include</option><option value="-">Exclude</option></select></div><br  class="clear" /></div><div class="group date_range"><div class="all_day line"><input type="checkbox" id="all_day" name="all_day" value="y" /> <label for="all_day">All Day Event</label></div><div class="from line"><div class="date leader"><label>From</label><input type="text" name="start_date" class="picker" value="" /></div><div class="time"><label>at</label><input type="text" name="start_time" /><select name="ampm"><option value="am">AM</option><option value="pm">PM</option></select></div><br class="clear" /></div><div class="to line"><div class="date leader"><label>To</label><input type="text" name="end_date" class="picker" value="" /></div><div class="time"><label>at</label><input type="text" name="end_time" /><select name="ampm"><option value="am">AM</option><option value="pm">PM</option></select></div><br class="clear" /></div></div><div class="group repeat line"><div class="repeat_select leader"><label>Repeat</label><select name="interval"><option value="none">None</option><option value="daily">Daily</option><option value="weekly">Weekly</option><option value="monthly">Monthly</option><option value="yearly">Yearly</option><option value="select_dates">Select Dates</option></select></div><div class="options"></div><br class="clear" /></div><br class="clear" /></div></div>';
		return output;
	};
	
	var restore_date_fields = function($context) {
		var $range = $context.closest('.rule').find('.date_range');
		if ($range.find('.date input, .time label').length == 0) {
			$range.find('.from .date label').after('<input type="text" name="start_date" class="picker" value="" />');
			$range.find('.to .date label').after('<input type="text" name="end_date" class="picker" value="" />');
			$range.find('.time').prepend('<label>at</label>');
			
			// Add date picker to From field
			var $rule = $context.closest('.rule');
			$('input[name=start_date]', $rule).datepicker({
				dateFormat: SSCalendar.dateFormat,
				changeMonth: true,
				changeYear: true,
				onSelect: function() {
					update_to_field_mindate($rule, true);
					update_picker_three_mindate($rule);
					update_end_by_mindate
				}
			});
			
			// Add date picker to To field
			$('input[name=end_date]', $rule).datepicker({
				dateFormat: SSCalendar.dateFormat,
				changeMonth: true,
				changeYear: true
			});
			update_from_field_mindate($rule);
			update_to_field_mindate($rule, true);
			update_end_by_mindate($rule);
		}
		
		$range.find('.date.inactive').removeClass('inactive');
	};
	
	var initialize_interval_details = function($rule) {
		create_selector_widget($('select.selector', $rule));
		toggle_monthly_by($rule);
		toggle_end_by($rule);
		create_select_dates_picker($rule);
	};
	
	var toggle_monthly_by = function($context) {
		if ($context == undefined) {
			$context = $('div.rule', $cal_fields);
		}
		$context.each(function() {
			if ($(this).find('select[name=interval]', $context).val() == 'monthly') {
				var $select = $(this).find('select[name=by]', $context);
				var val = $select.val();
				$(this).find('.'+val).show().end().find('.extended').filter(':not(.'+val+')').filter(':not(.dows)').hide();
				$select.unbind('change').change(function() {
					toggle_monthly_by($(this).closest('.rule'));
				});
			}
		});
	};
	
	var toggle_end_by = function($context) {
		if ($context == undefined) {
			$context = $cal_fields;
		}
		$context.find('select[name=end]').change(function() {
			var $select = $('select[name=end]', $context);
			switch($select.val()) {
				case 'by_date' :
					$select.parent().siblings('.options').remove().end().after(_html_end_by_date());
					$select.parent().siblings('.options').find('input').datepicker({
						dateFormat: SSCalendar.dateFormat,
						changeMonth: true,
						changeYear: true
					});
					update_end_by_mindate($(this).closest('.rule'));
					break;
				case 'after' :
					$select.parent().siblings('.options').remove().end().after(_html_end_after());
					break;
				default :
					$select.parent().siblings('.options').remove();
					break;
			};
			
		});
	};
	
	var renumber_rules = function() {
		$('.rule', $cal_fields).each(function(n) {
			$(this).find('.rule_number span').text(n+1);
		});
	};
	
	var save_calendar_data = function() {
		var success = false;
		var data = new Object;
		
		// Remove old saved data
		$('#calendar_data').remove();
		
		// Remove old errors
		$('#calendar_errors').remove();
		
		// Get the calendar ID
		data.calendar_id = $('select[name=calendar_calendar_id]', $cal_fields).val();
		
		// Prepare for our rule data
		data.rules = new Array;
		data.dates = new Array;
		
		// Iterate through the rules
		$('div.rule', $cal_fields).each(function() {
			var first = $(this).is('.first');
			var rule = {
				'rule_id': _get_rule_id($(this).find('input[name=rule_id]')),
				'rule_type': _get_rule_type($(this)),
				'all_day': _get_rule_all_day($(this)),
				'start_time': (_get_rule_all_day($(this)) == 'y') ? '' : _get_rule_time($(this).find('.date_range .from .time input')),
				'end_time': (_get_rule_all_day($(this)) == 'y') ? '' : _get_rule_time($(this).find('.date_range .to .time input'))
				};
			if ($(this).find('select[name=interval]').val() == 'select_dates') {
				if (first != true) {
					$(this).find('input[name=start_date], input[name=end_date]').remove();
				} else {
					rule.start_date = _get_rule_date($(this).find('input[name=start_date]'));
					rule.end_date = _get_rule_date($(this).find('input[name=end_date]'));
					data.rules.push(rule);
				}
				var dates = $(this).find('.picker_three').data('values');
				$.each(dates, function(k, v) {
					var o = {
						date: $.datepicker.formatDate('yymmdd', _get_date(v), SSCalendar.dateFormatSettings),
						start_time: rule.start_time,
						end_time: rule.end_time,
						rule_type: rule.rule_type
						};
					data.dates.push(o);
				});
			} else {
				rule.start_date = _get_rule_date($(this).find('input[name=start_date]'));
				rule.end_date = _get_rule_date($(this).find('input[name=end_date]'));
				rule.all_day = _get_rule_all_day($(this));
				rule.repeat_years = _get_rule_years($(this));
				rule.repeat_months = _get_rule_months($(this));
				rule.repeat_weeks = _get_rule_weeks($(this));
				rule.repeat_days = _get_rule_days($(this));
				rule.days_of_week = _get_rule_dow($(this));
				rule.relative_dow = _get_rule_relative($(this));
				rule.days_of_month = _get_rule_dom($(this));
				rule.months_of_year = '';
				rule.end_by = _get_rule_date($(this).find('input[name=end_by_date]'));
				rule.end_after = _get_rule_end_after($(this));
				data.rules.push(rule);
			}
		});
		
		// Save the rules as hidden inputs
		var string = '<div id="calendar_data">';
		if (data.calendar_id) {
			string += _create_hidden_input('calendar_id', data.calendar_id);
		}
		
		$.each(data.rules, function(k, rule) {
			$.each(rule, function(name, value) {
				string += _create_hidden_input(name+'['+k+']', value);
			});
		});
		
		$.each(data.dates, function(k, date) {
			$.each(date, function(name, value) {
				string += _create_hidden_input('occurrences['+name+'][]', value);
			});
		});
		
		string += '</div>';
		
		$('#entryform').append(string);
		
		// TODO: We could check for errors at some point...
		success = true;
		
		return success;
	};
	
	var _get_rule_id = function($context) {
		var val = $context.val();
		return (val == undefined) ? '' : val;
	};
	
	var _get_rule_type = function($context) {
		var val = $context.find('select[name=type]').val();
		return (val == undefined || val == '') ? '+' : val;
	};
	
	var _get_rule_date = function($field) {
		var val = $field.val();
		if (val == undefined) {
			return '';
		}
		
		val = $.datepicker.formatDate('yymmdd', _get_date(val), SSCalendar.dateFormatSettings);
		return val;
	};
	
	var _get_rule_all_day = function($context) {
		return ($('.all_day input:checkbox', $context).is(':checked')) ? 'y' : '';
	};
	
	var _get_rule_time = function($field) {
		var val = String($field.val());
		
		if (val == undefined || val == '') {
			return '';
		}
		
		var minute = '';
		var hour = '';
		var ampm = ($field.siblings('select[name=ampm]').length == 1) ? $field.siblings('select[name=ampm]').val() : '';
		
		// Just an hour
		if (val.length == 1 || val.length == 2) {
			minute = '00';
			hour = val;
		}  else if (val.indexOf(':') != -1) {
			var temp = val.split(':');
			hour = temp[0];
			minute = temp[1];
		} else if (val.length == 3 || val.length == 4) {
			minute = val.substring(val.length - 2);
			hour = val.substring(0, val.length - 2);
		} else {
			minute = '00';
			hour = '00';
		}
		
		// Remove leading zero, or else we won't like what parseInt() gives us
		if (hour.substring(0, 1) == 0) {
			hour = hour.substring(1);
		}
		
		if (ampm == 'pm' && parseInt(hour) < 12) {
			hour = parseInt(hour) + 12;
		} else if (ampm == 'am' && parseInt(hour) == 12) {
			hour = '00';
		}
		
		if (parseInt(hour) < 0 || parseInt(hour) > 23) {
			hour = '00';
		}
		
		if (parseInt(minute) < 0 || parseInt(minute) > 59) {
			minute = '00';
		}
		
		if (hour.length == 1) {
			hour = 0+hour;
		}
		
		return hour+minute;
	};
	
	var _get_rule_years = function($context) {
		var val = '';
		if ($('select[name=interval]', $context).val() == 'yearly') {
			val = $('input[name=every]', $context).val();
		}
		return val;
	};
	
	var _get_rule_months = function($context) {
		var val = '';
		if ($('select[name=interval]', $context).val() == 'monthly') {
			val = $('input[name=every]', $context).val();
		}
		return val;
	};
	
	var _get_rule_weeks = function($context) {
		var val = '';
		if ($('select[name=interval]', $context).val() == 'weekly') {
			val = $('input[name=every]', $context).val();
		}
		return val;
	};
	
	var _get_rule_days = function($context) {
		var val = '';
		if ($('select[name=interval]', $context).val() == 'daily') {
			val = $('input[name=every]', $context).val();
		}
		return val;
	};
	
	var _get_rule_dow = function($context) {
		var val = new Array;
		$('.dows .selector .item', $context).each(function() {
			if ($(this).data('selector') == true) {
				val.push($(this).data('value'));
			}
		});
		return val.join('|');
	};
	
	var _get_rule_relative = function($context) {
		var val = new Array;
		if ($('select[name=by]', $context).val() == 'by_relative') {
			$('.by_relative .selector .item', $context).each(function(){
				if ($(this).data('selector') == true) {
					val.push($(this).data('value'));
				}
			});
		}
		return val.join('|');
	};
	
	var _get_rule_dom = function($context) {
		var val = new Array;
		if ($('select[name=by]', $context).val() == 'by_date') {
			$('.by_date .selector .item', $context).each(function(){
				if ($(this).data('selector') == true) {
					val.push($(this).data('value'));
				}
			});
		}
		return val.join('|');
	};
	
	var _get_rule_end_after = function($context) {
		var val = '';
		if ($('select[name=end]', $context).val() == 'after') {
			val = $('input[name=end_after]', $context).val();
		}
		return val;
	}
	
	var _create_hidden_input = function(name, value) {
		return '<input type="hidden" name="'+name+'" value="'+value+'" />';
	};
	
	var show_hide_x = function() {
		var $rules = $('.rule', $cal_fields);
		
		// Hide X if there is only one rule
		if ($rules.length == 1) {
			$('.rule_close, .type', $rules).addClass('inactive');
		}
		// Hide X on the first rule if there is only one include rule
		else if ($('.type select[value=+]', $rules).length == 1) {
			$('.type select[value=+]', $rules).closest('.rule').find('.rule_close, .type').addClass('inactive');
		}
		// Show X on first rule
		else {
			$('.rule:first .rule_close', $cal_fields).removeClass('inactive');
		}
	}
	
	/***************************************************************************/
	
	// Systems are go!
	initialize();
	
	// 12 hour or 24 hour?
	var time_format = ($('.rule.first select[name=ampm]', $cal_fields).length > 0) ? '12' : '24';
	
	// When the user clicks submit, the work is just getting started...
	$('input[name=submit]').click(function() {
		var result = false;
		
		result = save_calendar_data();
		
		return result;
	});
	
	// Toggle open/close the Dates & Options fields
	$('.label a', $cal_fields).click(function() {
		
		// Hide 'em, Danno
		$('#calendar_wrapper', $cal_fields).toggle();
		
		// Swap the +/- image
		$(this).find('img').toggle();
		
		return false;
	});
	
	// Toggle the time fields when switching between Include and Exclude
	$('select[name=type]').live('change', function() {
		var val = $(this).val();
		if (val == '+') {
			$(this).closest('.inner').find('.date_range, .date_range *').removeClass('inactive');
		}
		else if ($(this).closest('.rule').find('select[name=interval]').val() == 'select_dates') {
			$(this).closest('.inner').find('.date_range').addClass('inactive');
		}
		else {
			$(this).closest('.inner').find('.date_range').find('.time, .all_day').addClass('inactive');
		}
		
		show_hide_x();
	});
	
	// Toggle display of time fields
	$('div.all_day input:checkbox').live('click', function() {
		toggle_time_fields($(this));
	});
	
	// Toggle display of event details
	$('#calendar_calendars select[name=calendar_calendar_id]', $cal_fields).change(function() {
		toggle_event_details();
	});
	
	// Toggle display of interval details
	$('.repeat_select select', $cal_fields).change(function() {
		toggle_interval_details($(this));
	});
	
	// Selector widget actions
	$('.selector .item a', $cal_fields).live('click', function() {
		var $item = $(this).closest('.item');
		toggle_selector_item($item);
		return false;
	});
	
	// Add a new rule
	$('#calendar_new_date a').click(function() {
		var $rule = $(_html_new_rule());
		
		// Get rid of am/pm dropdowns if we're in 24 hour time
		if (time_format == '24') {
			$rule.find('select[name=ampm]').remove();
		}
		
		// Add rule number
		$rule.find('div.rule_number span').text($('.rule', $cal_fields).length+1);
		
		// Add date picker to From field
		$('input[name=start_date]', $rule).datepicker({
			dateFormat: SSCalendar.dateFormat,
			changeMonth: true,
			changeYear: true,
			onSelect: function() {
				update_to_field_mindate($rule, true);
				update_picker_three_mindate($rule);
				update_end_by_mindate($rule);
				update_picker_three_mindate($rule);
			}
		});
		
		// Add date picker to To field
		$('input[name=end_date]', $rule).datepicker({
			dateFormat: SSCalendar.dateFormat,
			changeMonth: true,
			changeYear: true
		});
		update_from_field_mindate($rule);
		update_to_field_mindate($rule, true);
		
		// Toggle display of interval details
		$('.repeat_select select', $rule).change(function() {
			toggle_interval_details($(this));
		});
		
		$('#calendar_wrapper div.rule:last').after($rule);
		
		show_hide_x();
		
		return false;
	});
	
	// Close the rule
	$('.rule_close', $cal_fields).live('click', function() {
		$firstrule = $(this).closest('.rule.first');
		
		if ($firstrule.length == 1) {
			var $includes = $('.type select[value=+]', $cal_fields).not($firstrule.find('.type select'));
			if ($includes.length > 0) {
				$includes.eq(0).closest('.rule').addClass('first').replaceAll($firstrule).find('.group').addClass('first');
			}
		} else {
			$(this).closest('.rule').remove();
		}
		
		renumber_rules();
		show_hide_x();
		
		return false;
	});

});
