/**
 * @author Alex Heyd
 * All options within the new methods are accessed via options.name.
 * Example:
 *
 * $.fn.centerObj = function(options){
 *	var options = jQuery.extend(
 *		{
 *			left: 0,
 *			top: 0
 *		},
 *		options
 *	);
 *
 * To access the left property, do options.left
 *
 * List of all functions and methods:
 *
 * $.fn.accordion()
 * $.fn.concatenate()
 * $.fn.clearOptions()
 * $.fn.addRange()
 * $.fn.addOption()
 * $.fn.addOptgroup()
 * $.fn.popWin()
 * $.fn.centerObj()
 * $.fn.conditional()
 *
 * acceptAge()
 * concatDate()
 * setDateEvents()
 *
 */



/**
 * Accordion Menu
 * Example: $('dl.accordion').accordion();
 * $('dl.accordion') refers to a <dl> element. The class name can be whatever you want.
 * The HTML must be structured very specifically as such:
 *
 * <dl>
 * 		<dt><a href="link">Header Link That Activates The Accordion</a></dt>
 * 		<dd>Content goes here</dd>
 * </dl>
 */
$.fn.accordion = function(){
	$(this).children('dt').find('a').click(
		function(){
			$(this)
				.parent()
				.next('dd')
				.slideToggle('normal');

			return false;
		}
	)

	return this;
}




/**
 * Concatenate Checkboxes into a hidden text field
 * Example: $('input.classname').concatenate('hiddenField');
 * $('input.classname') is generally a checkbox or radio button with the same class name to group them together
 * hiddenField is the id of the hidden text field where the values should be concatenated
 * @param {Object} target
 */
$.fn.concatenate = function(target){
	$(this).click(
		function(){
			var source = $(this).attr('class');

			$('#' + target).val('');
			$('input').filter('.' + source).each(
				function(){
					if(this.checked == true){
						if($('#' + target).val() == ''){
							$('#' + target).val($(this).val());
						}
						else{
							$('#' + target).val($('#' + target).val() + ',' + $(this).val());
						}
					}
				}
			)
		}
	)

	return this;
}





/**
 * Clear all options in a select box
 * Example: $('#dropdown').clearOptions();
 */
$.fn.clearOptions = function(){
	return this.each(
		function(){
			$(this).empty();
		}
	);
}




/**
 * Adds options to a select box within a specified range
 * Example: $('#dropdown').addRange('1', '5');
 *
 * Before:
 * <select id="dropdown">
 * 		<option value="">Select One</option>
 * </select>
 *
 * Result:
 * <select id="dropdown">
 * 		<option value="">Select One</option>
 * 		<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>
 * </select>
 *
 * @param {Object} low
 * @param {Object} high
 */
$.fn.addRange = function(low, high, pad){
	return this.each(
		function(){
			for (var i = low; i <= high; i++){
				var tmp = i.toString();

				if(tmp.length == 1 && pad == true){
					tmp = '0' + tmp;
				}

				$(this).append('<option value="' + tmp + '">' + tmp + '</option>');
			}
			this.selectedIndex = 0;
		}
	);
}



/**
 * Adds an option to a select box.
 * Example: $('#dropdown').addOption('value', 'label');
 *
 * Before:
 * <select id="dropdown">
 * 		<option value="">Select One</option>
 * </select>
 *
 * Result:
 * <select id="dropdown">
 * 		<option value="">Select One</option>
 * 		<option value="value">label</option>
 * </select>
 *
 * If the last option in the select box is an optgroup, this will automatically include it within the optgroup.
 *
 * @param {Object} value
 * @param {Object} label
 */
$.fn.addOption = function(value, label){
	return this.each(
		function(){
			var index = $(this).children().length - 1;
			if ($(this).children().eq(index).attr('class') == 'optgroup'){
				$(this).children().eq(index).append('<option value="' + value + '">' + label + '</option>');
			}
			else{
				$(this).append('<option value="' + value + '">' + label + '</option>');
			}
			this.selectedIndex = 0;
		}
	);
}




/**
 * Adds an optgroup to a select box.
 * Example: $('#dropdown').addOptgroup('labelName');
 *
 * Before:
 * <select id="dropdown">
 * 		<option value="">Select One</option>
 * </select>
 *
 * Result:
 * <select id="dropdown">
 * 		<option value="">Select One</option>
 * 		<optgroup class="optgroup" label="labelName">
 * 		</optgroup>
 * </select>
 *
 * If the last option in the select box is an optgroup, the following addOption will include the option within the last optgroup.
 *
 * @param {Object} label
 */
$.fn.addOptgroup = function(label){
	return this.each(
		function(){
			$(this).append('<optgroup class="optgroup" label="' + label + '">');
		}
	);
}




/**
 * Sets up the conditional events and values to be used.
 * Example: $('#dropdown').conditional(jsonObj, 'target);
 *
 * jsonObj is a JSON object determined on the front end
 * target is the id of the targeted dropdown to populate with the values.
 *
 * @param {Object} json
 * @param {Object} targetID
 */
$.fn.conditional = function(json, targetID){
	$(this).change(
		function(){
			var thisCase = $(this).val();
            try
            {
			    for (var i = 0; i < json.conditions.length; i++)
			    {

				    var thisCondition = json.conditions[i];

				    switch (thisCase){

					    case thisCondition.name:
						    $('#' + targetID).clearOptions();
						    $('#' + targetID).addOption('', '');

						    for(var j = 0; j < thisCondition.options.length; j++){

							    var thisOption = thisCondition.options[j];

							    if(thisOption.optgroup == true){
								    $('#' + targetID).addOptgroup(thisOption.label);
							    }
							    else {
								    $('#' + targetID).addOption(thisOption.value, thisOption.label);
							    }
						    }

					    break;
				    }
			    }
			}catch(e)
			{}
		}
	)
}



/**
 * Defines either a minimum or maximum age filter. This function is automatically called from within the concatAge() function.
 * Example: acceptAge('yearID', 'monthID', 'dayID', 'min', 18);
 * Result: The user must be 18 or over.
 *
 * Example:  acceptAge('yearID', 'monthID', 'dayID', 'max', 35);
 * Result: The user must be 35 or under.
 *
 * idYear: id of the dropdown used for Year
 * idMonth: id of the dropdown used for Month
 * idDay: id of the dropdown used for Day
 * thisType: 'min' or 'max' to determine what type of filter to use
 * age: whole integer
 *
 * @param {Object} idYear
 * @param {Object} idMonth
 * @param {Object} idDay
 * @param {Object} thisType
 * @param {Object} age
 */
function acceptAge(idYear, idMonth, idDay, thisType, age){
	var thisYear = $('#' + idYear).val();
	var thisMonth = $('#' + idMonth).val();
	var thisDay = $('#' + idDay).val();

	var currentDate = new Date();
	var currentYear = currentDate.getFullYear();
	var currentMonth = (currentDate.getMonth()) + 1;
	var currentDay = currentDate.getDate();

	var theirAge = currentYear - thisYear;
	var accepted = true;

	if (thisType == 'min'){
		if(theirAge < age){
			accepted = false;
		}

		if (theirAge == age){
			if(thisMonth > currentMonth){
				accepted = false;
			}

			if(thisMonth == currentMonth){
				if(thisDay > currentDay){
					accepted = false;
				}
			}
		}
	}

	if (thisType == 'max'){
		if(theirAge > age){
			accepted = false;
		}

		if (theirAge == age){
			if(thisMonth < currentMonth){
				accepted = false;
			}

			if(thisMonth == currentMonth){
				if(thisDay < currentDay){
					accepted = false;
				}
			}
		}
	}

	return accepted;
}




/**
 * Concatenates the date into a hidden field. This function is linked to the onChange event of the dropdowns for the date.
 * Example: concatDate('yearID', 'monthID', 'dayID', 'concatID');
 *
 * idYear: id of the dropdown used for Year
 * idMonth: id of the dropdown used for Month
 * idDay: id of the dropdown used for Day
 * idConcat: id of the hidden field where to concatenate the date
 * dateType: if set to 'dob' it will include the acceptAge() function
 *
 * @param {Object} idYear
 * @param {Object} idMonth
 * @param {Object} idDay
 * @param {Object} idConcat
 */
function concatDate(idYear, idMonth, idDay, idConcat, dateType, filterType, ageFilter){
	var thisYear = $('#' + idYear).val();
	var thisMonth = $('#' + idMonth).val();
	var thisDay = $('#' + idDay).val();

	if (dateType == 'dob'){
		var accepted = acceptAge(idYear, idYear, idDay, filterType, ageFilter);
	}
	else{
		var accepted = true;
	}

	if(accepted == true){
		if ((thisYear != '') && (thisMonth != '') && (thisDay != '')){
			$('#' + idConcat).val(thisYear + '-' + thisMonth + '-' + thisDay);
		}
		else {
			$('#' + idConcat).val('');
		}
	}
	else{
		$('#' + idConcat).val('');
	}
}



/**
 * Links the event handlers to the dropdowns.
 * Example: setDateEvents('yearID', 'monthID', 'dayID', 'concatID', 'dob', 'min', 18);
 *
 * idYear: id of the dropdown used for Year
 * idMonth: id of the dropdown used for Month
 * idDay: id of the dropdown used for Day
 * idConcat: id of the hidden field where to concatenate the date
 * dateType: if set to 'dob' it will include the acceptAge() function (optional)
 * filterType: defines if there should be a filter ('min' or 'max') (optional)
 * ageFilter: whole integer to filter against (optional)
 *
 * @param {Object} idYear
 * @param {Object} idMonth
 * @param {Object} idDay
 * @param {Object} idConcat
 */
function setDateEvents(idYear, idMonth, idDay, idConcat, dateType, filterType, ageFilter){

	dateType = (typeof dateType == 'undefined') ? 'date' : dateType;
	filterType = (typeof filterType == 'undefined') ? 'none' : filterType;
	ageFilter = (typeof ageFilter == 'undefined') ? 0 : ageFilter;

	$('#' + idYear).change(
		function(){
			var thisYear = $(this).val();
			var thisMonth = $('#' + idMonth).val();

			if (thisMonth == '02'){
				if(thisYear % 4 == 0){
					$('#' + idDay).addRange(1, 29);
				}
				else{
					$('#' + idDay).addRange(1, 28);
				}
			}

			concatDate(idYear, idMonth, idDay, idConcat, dateType, filterType, ageFilter);
		}
	)

	$('#' + idMonth).change(
		function(){
			var thisYear = $('#' + idYear).val();
			var thisMonth = $(this).val();

			if (thisMonth == '01' || thisMonth == '03' || thisMonth == '05' || thisMonth == '07' || thisMonth == '08' || thisMonth == '10' || thisMonth == '12'){
				$('#' + idDay).addRange(1, 31);
			}
			else{
				if (thisMonth == '02'){
					if(thisYear % 4 == 0){
						$('#' + idDay).addRange(1, 29);
					}
					else{
						$('#' + idDay).addRange(1, 28);
					}
					if(thisYear == ''){
						$('#' + idDay).addRange(1, 28);
					}
				}
				else{
					$('#' + idDay).addRange(1, 30);
				}
			}

			concatDate(idYear, idMonth, idDay, idConcat, dateType, filterType, ageFilter);
		}
	)

	$('#' + idDay).change(
		function(){
			concatDate(idYear, idMonth, idDay, idConcat, dateType, filterType, ageFilter);
		}
	)
}



/**
 * Creates a popup window
 * Example: $('a.popLink').popWin(
 * 				{
 * 					width: 400,
 * 					title: 'new title'
 * 				}
 * 			)
 *
 * All parameters are optional.
 *
 * width: width of the window
 * height: height of the window
 * title: title to display at the top of the window (defaults to the rel attribute of the anchor tag)
 * url: URL to load into the window via AJAX (defaults to the href attribute of the anchor tag)
 * left: left offset from the center in px to display window
 * top: top offset from the center in px to display window
 *
 * @param {Object} options
 */
$.fn.popWin = function(options){
	var options = jQuery.extend(
		{
			width: 600,
			height: 500,
			title: $(this).attr('rel'),
			url: $(this).attr('href'),
			left: 0,
			top: 0
		},
		options
	);

	$(this).click(
		function(){
			$('body')
				.append('<div class="popWindow"><a href="#" class="winClose">close</a><h2>' + options.title + '</h2><div class="popContent"></div></div>')
				.children('div.popWindow')
				.css(
					{
						width: options.width + 'px',
						height: options.height + 'px'
					}
				)
				.find('div.popContent')
				.load(options.url)
				.parent()
				.fadeIn('normal')
				.centerObj({
					left: options.left,
					top: options.top
				});

			$('a.winClose')
				.click(
					function(){
						$(this)
							.parent()
							.fadeOut(1000)
							.empty()
							.remove();
					}
				)

			return false;
		}
	)

	return this;
}



/**
 * Centers an element relative to the user's viewport
 * Example: $('div').centerObj({left: -150, top: 10});
 *
 * All parameters are optional. In which case the object will be centered. Make sure the object being centered is set to position: absolute.
 *
 * left: left offset from the center in px to display window
 * top: top offset from the center in px to display window
 *
 * Requires dimensions.js
 *
 * @param {Object} options
 */
$.fn.centerObj = function(options){
	var options = jQuery.extend(
		{
			left: 0,
			top: 0
		},
		options
	);

	var viewWidth = $(window).width();
	var viewHeight = $(window).height();
	var thisWidth = $(this).width();
	var thisHeight = $(this).height();

	var leftPos = (viewWidth/2) - (thisWidth/2);
	var topPos = (viewHeight/2) - (thisHeight/2);
	leftPos = leftPos + options.left;
	topPos = topPos + options.top;

	$(this).css('left', leftPos + 'px');
	$(this).css('top', topPos + 'px');

	return this;
}

