(function($){
	
	$.fn.calendar = function (options){
		return $(this).each(function(){
			
			var now = new Date();
			
			date = {
				date	:	now.getDate(),
				day		:	now.getDay(),
				month	:	now.getMonth(),
				year	:	now.getFullYear(),
				now		:	now
			}; /* date */

			$.extend(this,defaultParams,options,date);
			
			$(this).append(format(frameHTML,[this.months[this.month],header.call(this),construct.call(this,this.year,this.month)]));
			
			obj = this;
			
			$(this).find('.jqc-prev').live('click',function(){
				$(obj).html(format(frameHTML,[obj.months[getNewMonth(obj.shownMonth - 1)],header.call(obj),construct.call(obj,getNewYear(obj.shownYear,obj.shownMonth - 1),getNewMonth(obj.shownMonth - 1))]));
			});
			$(this).find('.jqc-next').live('click',function(){
				$(obj).html(format(frameHTML,[obj.months[getNewMonth(obj.shownMonth + 1)],header.call(obj),construct.call(obj,getNewYear(obj.shownYear,obj.shownMonth + 1),getNewMonth(obj.shownMonth + 1))]));
			});
			
		});
		
	}/* $.fn.calendar */

	var getNewMonth = function (month){
		var now = new Date();
		return date = new Date(now.getFullYear(),month,1).getMonth();
	}/* getNewMonth */
	var getNewYear = function (year,month){
		//var now = new Date();
		return date = new Date(year,month,1).getFullYear();
	}/* getNewYear */

	var defaultParams = {
		months		:	['January','February','March','April','May','June','July','August','September','October','November','December'],
		monthsShort	:	['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
		days		:	['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
		daysShort	:	['Su','Mo','Tu','We','Th','Fr','Sa']
	}/* defaultParams */
	
	/** EDITABLE REGIONS
	 * 0 = month
	 * 1 = days
	 * 2 = calendar
	 */
	var frameHTML = [
			'<div class="jqc-prev"></div>',
			'<h2>{0}</h2>',
			'<div class="jqc-wrapper">',
				'<div class="jqc-header">{1}</div>',
				'<div class="jqc-calendar">{2}</div>',
			'</div>',
			'<div class="jqc-next"></div>'
	].join('');/* frameHTML */
	
	var header = function (){
		output = '';
		for(i = 0 ; i < 7 ; i++){
			output += '<div>' + this.daysShort[i] + '</div>';
		}
		return output;
	};/* header */
	
	
	
	var construct = function(year,month){
		var output = $('<div />');
		i = 1;
		if(month > 11){
			
			month = month - 12;
			year++;
		};
		
		var currentDay = new Date(year,month,1);
		this.shownYear = currentDay.getFullYear();
		this.shownMonth = currentDay.getMonth();
		//	PREVIOUS MONTH
		if(currentDay.getDay() > 0 && currentDay.getDay() <= 6){
			j = 1;
			while(j <= currentDay.getDay()){
				x = 'x';
				var lastDate = new Date(year,month,1 - j);
				var ele = $('<div class="prevMonth past">' + lastDate.getDate() + '</div>')	//	get dates
				ele.data = {
					year	:	lastDate.getFullYear(),
					month	:	lastDate.getMonth(),
					date	:	lastDate.getDate()
				};
				output.prepend(ele);
				j++;
			};
		};
		//	THIS MONTH
		while(currentDay.getMonth() === month){
			var ele = $('<div class="activeMonth">' + i + '</div>')
			if (currentDay.getFullYear() === this.year && 
				currentDay.getMonth() === this.month &&
				currentDay.getDate() === this.date){
				ele.addClass('today');
			};
			
			if(currentDay.getDate() < this.date && currentDay.getMonth() === this.month && currentDay.getFullYear() === this.year ){
				ele.addClass('past');
			};
			ele.data = {
				year	:	currentDay.getFullYear(),
				month	:	currentDay.getMonth(),
				date	:	currentDay.getDate()
			};
			output.append(ele);
			i++;
			currentDay = new Date(year,month,i);
		};
		//	NEXT MONTH
		i = output.children().length;
		j = 1;
		while(i < 42){
			currentDay = new Date(year,month,i);
			var ele = $('<div class="nextMonth">' + j + '</div>')
			ele.data = {
				year	:	currentDay.getFullYear(),
				month	:	currentDay.getMonth(),
				date	:	j
			};
			output.append(ele);
			i++;
			j++;
		}
		if($.isFunction(this.complete)){
			var month = {
				month:this.shownMonth,
				longMonth:this.months[this.shownMonth],
				shortMonth:this.monthsShort[this.shownMonth]
			};
			this.complete.call(this,output.children('.activeMonth'),this.shownYear,month);
		};
		return output.html();
	};/* construct */
	
	
	
	var format = function (source, params) {
			if ( arguments.length == 1 ){
				return function() {
					var args = $.makeArray(arguments);
					args.unshift(source);
					return $.validator.format.apply( this, args );
				};
			};
			if ( arguments.length > 2 && params.constructor != Array  ) {
				params = $.makeArray(arguments).slice(1);
			};
			if ( params.constructor != Array ) {
				params = [ params ];
			};
			$.each(params, function(i, n) {
				source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
			});
			return source;
		};/* format */

})(jQuery);
