;(function($) {
	$.fancyCountdown = {version: '1.0'};
	
	$.fn.fancyCountdown = function(arg) {
		
		var options = $.extend({},$.fn.fancyCountdown.defaults,arg);
		var $elem, timerInterval, targetDate, startTimeSet = false, currentSec1, currentSec2, currentMin1, currentMin2, currentHour1, currentHour2, currentDay1, currentDay2, currentDay3 ;
	    var second1Digits, second2Digits, minute1Digits, minute2Digits, hour1Digits, hour2Digits, day1Digits, day2Digits, day3Digits;
		
			function _init(elem) {
				
				$elem = $(elem);	
				$elem.addClass('fc-panel');
							
				//check if digit unit is requested
				if(options.digits.seconds) {
				  second1Digits = _createDigitUnit('seconds');
				  second2Digits = _createDigitUnit('seconds');
				}
				if(options.digits.minutes) {
				  if(options.digits.seconds) _createColon();
				  minute1Digits = _createDigitUnit('minutes');
				  minute2Digits = _createDigitUnit('minutes');
				}
				if(options.digits.hours) {
				   if(options.digits.minutes) _createColon();
				  hour1Digits = _createDigitUnit('hours');
				  hour2Digits = _createDigitUnit('hours');
				}
				if(options.digits.days) {
				  if(options.digits.hours) _createColon();
				  day1Digits = _createDigitUnit('days');
				  day2Digits = _createDigitUnit('days');
				  day3Digits = _createDigitUnit('days');
				}
				
				//set captions if requested
				if(options.captions) {
					var offset = parseInt($elem.children('.fc-digitUnit').css('margin-right')) * 0.5;
					if(options.digits.seconds) _createTitle("seconds", $($elem.children('.fc-seconds')[1]).position().left-offset);
					if(options.digits.minutes) _createTitle("minutes", $($elem.children('.fc-minutes')[1]).position().left-offset);
					if(options.digits.hours) _createTitle("hours", $($elem.children('.fc-hours')[1]).position().left-offset);
					if(options.digits.days) _createTitle("days", $($elem.children('.fc-days')[1]).position().left+options.digitUnitWidth*0.5);						
				}
				
				//set font for the digit
				Cufon.now();
				Cufon.replace('.fc-digitUnit',{ fontFamily: options.fontName });		
	
		        if(options.autoStart) $.fancyCountdown.start();
			};
			
			function _timer() {
				
				//target date depending on the timezone
				targetDate = Date.UTC(options.year, options.month-1, options.day, options.hour-options.timezone, options.minute, options.second);
				var now = new Date();
				
				//calculate seconds, minutes, hours and days
				var timeLeft = targetDate - now.getTime();
				var seconds = Math.floor(timeLeft / 1000);
			    var minutes = Math.floor(seconds / 60);
			    var hours = Math.floor(minutes / 60);
			    var days = Math.floor(hours / 24);
				seconds %= 60;
			    minutes %=60;
			    hours %=24;
				
				//getting the different digits of each time unit
				var sec1 = Math.floor(seconds % 10);
				var sec2 = Math.floor(seconds / 10);
				var min1 = Math.floor(minutes % 10);
				var min2 = Math.floor(minutes / 10);
				var hour1 = Math.floor(hours % 10);
				var hour2 = Math.floor(hours / 10);
				var day1 = Math.floor(days % 10);
				var day2 = Math.floor((Math.floor(days / 10)) % 10);
				var day3= Math.floor(days / 100);
				
				//set the start digits once
				if(!startTimeSet) {
					currentSec1 = sec1;
					currentSec2 = sec2;
					currentMin1 = min1;
					currentMin2 = min2;
					currentHour1 = hour1;
					currentHour2 = hour2;
					currentDay1 = day1;
					currentDay2 = day2;
					currentDay3 = day3;
					
					var digitValue = -2;
					for(var i=0; i < 4; ++i) {
						if(options.digits.seconds) {
						  second1Digits[i].text(_calculateTimeRange(sec1+digitValue, 0, 9));
						  second2Digits[i].text(_calculateTimeRange(sec2+digitValue, 0, 5));
						}
						if(options.digits.minutes) {
						  minute1Digits[i].text(_calculateTimeRange(min1+digitValue, 0, 9));
						  minute2Digits[i].text(_calculateTimeRange(min2+digitValue, 0, 5));
						}
						if(options.digits.hours) {
						  hour1Digits[i].text(_calculateTimeRange(hour1+digitValue, 0, 9));
						  hour2Digits[i].text(_calculateTimeRange(hour2+digitValue, 0, 2));
						}
						if(options.digits.days) {
						  day1Digits[i].text(_calculateTimeRange(day1+digitValue, 0, 9));
						  day2Digits[i].text(_calculateTimeRange(day2+digitValue, 0, 9));
						  day3Digits[i].text(_calculateTimeRange(day3+digitValue, 0, 9));
						}
						++digitValue;
					}
					Cufon.refresh('.fc-digitUnit');				
				}
				startTimeSet = true;
				
				//check if target date is reached
				if(timeLeft > 0)
				{
					//show next second of digit one when the current second has changed
					if(currentSec1 != sec1) {
						Cufon.refresh('.fc-digitUnit');
						if(options.digits.seconds) _moveDigits(second1Digits, _calculateTimeRange(sec1-2, 0, 9));
						currentSec1 = sec1;
					}
					//show next second of digit two when the current second has changed
					if(currentSec2 != sec2) {
						if(options.digits.seconds) _moveDigits(second2Digits, _calculateTimeRange(sec2-2, 0, 5));
						currentSec2 = sec2;
					}
					//show next minute of digit one when the current minute has changed
					if(currentMin1 != min1) {
						if(options.digits.minutes) _moveDigits(minute1Digits, _calculateTimeRange(min1-2, 0, 9));
						currentMin1 = min1;
					}
					//show next minute of digit two when the current minute has changed
					if(currentMin2 != min2) {
						if(options.digits.minutes) _moveDigits(minute2Digits, _calculateTimeRange(min2-2, 0, 5));
						currentMin2 = min2;
					}
					//show next hour of digit one when the current hour has changed
					if(currentHour1 != hour1) {
						if(options.digits.hours) _moveDigits(hour1Digits, _calculateTimeRange(hour1-2, 0, 9));					
						currentHour1 = hour1;
					}
					//show next hour of digit two when the current hour has changed
					if(currentHour2 != hour2) {
						if(options.digits.hours) _moveDigits(hour2Digits, _calculateTimeRange(hour2-2, 0, 2));	
						currentHour2 = hour2;
					}
					//show next day of digit one when the current day has changed
					if(currentDay1 != day1) {
						if(options.digits.days) _moveDigits(day1Digits, _calculateTimeRange(day1-2, 0, 9));
						currentDay1 = day1;
					}
					//show next day of digit two when the current day has changed
					if(currentDay2 != day2) {
						if(options.digits.days) _moveDigits(day2Digits, _calculateTimeRange(day2-2, 0, 9));
						currentDay2 = day2;
					}
					//show next day of digit three when the current day has changed
					if(currentDay3 != day3) {
						if(options.digits.days) _moveDigits(day3Digits, _calculateTimeRange(day3-2, 0, 9));
						currentDay3 = day3;
					};
				}
				else {
					$.fancyCountdown.stop();
					$.fancyCountdown.reset();
					options.callback();
					Cufon.refresh('.fc-digitUnit');
				}
			};
			
			//main movement for the digits
			function _moveDigits(digits, lastDigitValue) {			
				digits[0].animate({top: -($(digits[0]).height()-options.topDigitOffset)}, 300);
				digits[1].animate({'top': 0}, 300);
				digits[2].animate({'top': options.digitUnitHeight-options.bottomDigitOffset}, 300);
				digits[3].animate({'top': options.digitUnitHeight}, 300, function() {
					var lastDigit = digits.pop();
					$(lastDigit).css('top', -$(lastDigit).height()+"px");
					lastDigit.text(lastDigitValue);
					digits.unshift(lastDigit);				
				  }
				);
			};
			
			//calculate the range between two numbers
			function _calculateTimeRange(value, minValue, maxValue) {
				if(value < 0) return maxValue+value+1;
				else if(value > maxValue) return minValue+value-maxValue-1;
				else return value;
			};
			
			//create the digit unit with 4 digits and the overlay
			function _createDigitUnit(id) {
				
				$elem.prepend("<div style='width:"+options.digitUnitWidth+"px;height:"+options.digitUnitHeight+"px;background:"+options.fillColor+";' class='fc-digitUnit fc-"+id+"'><div class='fc-digits'><ul><li>8</li><li>9</li><li>0</li><li>1</li></ul></div><div style='width:"+options.digitUnitWidth+"px;height:"+options.digitUnitHeight+"px;' class='fc-digitOverlay'></div></div>");
				
				var digits = $elem.children('div:first').find('.fc-digits li').css({'width': options.digitUnitWidth+"px", 'line-height': options.digitUnitHeight+"px"});
				var $digits = [];
				
				$digits[0] = $(digits[0]).css('top', -$(digits[0]).height()+"px");
				$digits[1] = $(digits[1]).css('top', -($(digits[0]).height()-options.topDigitOffset)+"px");
				$digits[2] = $(digits[2]).css('top', '0px');
				$digits[3] = $(digits[3]).css('top', options.digitUnitHeight-options.bottomDigitOffset+"px");
				
				return $digits;
			};
			
			//create a colon
			function _createColon() {
				$elem.prepend("<div style='width:"+options.colonUnitWidth+"px;height:"+options.digitUnitHeight+"px;background:"+options.fillColor+";' class='fc-digitUnit'><div style='width:"+options.colonUnitWidth+"px;line-height:"+options.digitUnitHeight+"px;' class='fc-digitOverlay fc-colon'>:</div></div>");
			};
			
			//create a title
			function _createTitle(text, xPos) {			
				$elem.append("<div class='fc-captions'>"+text+"</div>");
				xPos = xPos - $elem.find('div:last').width() * 0.5;
				$elem.find('div:last').css({
					'left': xPos,
				    'top': options.digitUnitHeight
				});
			};
			
			//start the countdown
			$.fancyCountdown.start = function() {
				if(timerInterval) return;
				startTimeSet = false;
				timerInterval = setInterval(_timer, 100);
			};
			
			//stop the countdown
			$.fancyCountdown.stop = function() {
				if(!timerInterval) return;
				clearInterval(timerInterval);
				timerInterval = null;
			};
			
			//reset all digits
			$.fancyCountdown.reset = function() {
			  $elem.find('.fc-digits li').stop(true, true);			  		
			  for(var i=0; i < 4; ++i) {
				  if(options.digits.seconds) {
					second1Digits[i].text((8+i)%10);
					second2Digits[i].text((4+i)%6);
				  }
				  if(options.digits.minutes) {
					minute1Digits[i].text((8+i)%10);
					minute2Digits[i].text((4+i)%6);
				  }
				  if(options.digits.hours) {
					hour1Digits[i].text((8+i)%10);
					hour2Digits[i].text((1+i)%3);
				  }
				  if(options.digits.days) {
					day1Digits[i].text((8+i)%10);
					day2Digits[i].text((8+i)%10);
					day3Digits[i].text((8+i)%10);
				  }
			  }			
			};
			
			//set the fill color of each unit
			$.fancyCountdown.fillColor = function(color) {
				$elem.children('.fc-digitUnit').css('background', color);
			};
			
			//set the target date
			$.fancyCountdown.targetDate = function(year, month, day, hour, minute, second) {
				hour = hour || 0;
				minute = minute || 0;
				second = second || 0;
				
				options.year = parseInt(year);
				options.month = parseInt(month), 
				options.day = parseInt(day);
				options.hour = parseInt(hour);
				options.minute = parseInt(minute);
				options.second = parseInt(second);
				startTimeSet = false;
			};
			
			//set the timezone
			$.fancyCountdown.timezone = function(value) {
	            options.timezone = parseFloat(value);
			};

		return this.each(function() {_init(this)});
	};
	
	$.fn.fancyCountdown.defaults = {
		year: 2012, //4 digits
		month: 12, //1-12
		day: 31, //1-31
		hour: 0, //0-23
		minute: 0, //0-59
		second: 0, //0-59
		digitUnitWidth: 60, //the width of a digit unit
		digitUnitHeight: 80, //the height of a digit unit
		colonUnitWidth: 20, //the width of a colon unit
		topDigitOffset: 25, //the offset of the top digit, which comes next after the current digit
		bottomDigitOffset: 24, //the offset of the bottom digit, which is after the current digit
		timezone: 1, //the timezone you would like to target
		fillColor: '#005152', //the fill color the units
		fontName: 'Harabara', //the fontName you are using for the digits. This font must be also embed with cufon.
		autoStart: true, //enable/disbale auto-start
		captions: true, //enable/disable the captions
		digits: {days:true, hours:true, minutes:true, seconds:true}, //enable/disbale each time unit
		callback: function(){} // a callback function that will be called, when the target date is reached
	};
})(jQuery);
