/**
 * opening countdown
 * 
 * @package		openingCountdown
 * @author		Bjoern Bartels <bb@p-ad.de>, P.AD.Werbeagentur
 * @copyright	(c) 2010  P.AD.Werbeagentur
 * 
 * @param	OBJECT	oOptions
 * @return	OBJECT|openingCountdown
 */
function openingCountdown ( oOptions ) {
	
	var $this			=	this;
	var clockElement	=	null;
	var oTimerOptions	=	{};
	var oSchedule		=	{};
	var userEvents		=	{};
	var onBeforeOpen	=	function () {};
	var onBeforeClose	=	function () {};

	var days = [ 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday' ];
	var daysShort = [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ];
	
	function init ( oInitOptions ) {
		if ( (typeof oInitOptions == 'undefined') ) {
			oInitOptions	=	{};
		}
		oTimerOptions		=	oInitOptions;
		oTimerOptions.init	=	new Date();
		if ( (typeof oTimerOptions.interval == 'undefined') ) {
			oTimerOptions.interval		=	5000;
		}
		if ( (typeof oTimerOptions.schedule != 'undefined') ) {
			oSchedule					=	oTimerOptions.schedule;
		}
		if ( (typeof oTimerOptions.onBeforeOpen != 'function') ) {
			oTimerOptions.onBeforeOpen	=	function () {};
		}
		onBeforeOpen = oTimerOptions.onBeforeOpen;
		if ( (typeof oTimerOptions.onBeforeClose != 'function') ) {
			oTimerOptions.onBeforeClose	=	function () {};
		}
		onBeforeClose = oTimerOptions.onBeforeClose;
		if (oTimerOptions.autoStart) {
			startCountdown();
		}
	}

	function startCountdown () {
		setInterval($this.checkEvents, oTimerOptions.interval);
	}
	
	function stopCountdown () {
		clearInterval($this.checkEvents);
	}
	
	function removeEvent ( sEventId ) {
		$this.userEvents[sEventId]	=	null;
	}
	
	function addEvent ( oEventOptions ) {
		if ( 
			(typeof oEventOptions == 'undefined') || 
			(typeof oEventOptions.id == 'undefined') || (typeof oEventOptions.start == 'undefined') || (typeof oEventOptions.callback != 'function')
		) {
			return (false);
		}
		
		var oEvent					=	oEventOptions;
		$this.userEvents[oEvent.id]	=	oEvent;
		
		return ($this);
	}
	
	function checkEvents () {
		var oCurrentDateTime = new Date();
		for ( iEvent in $this.userEvents ) {
			var oEvent = $this.userEvents[iEvent];
			if ( oCurrentDateTime.getTime() >= oEvent.start.getTime() ) {
				if ( (typeof oEvent.stop == 'undefined') || (oCurrentDateTime.getTime() <= oEvent.stop.getTime()) ) {					
					if ( !oEvent.runOnce || (oEvent.runOnce && !oEvent.lastRun) ) {						
						oEvent.time			=	oCurrentDateTime;
						if (oEvent.runOnce) {
							oEvent.lastRun	=	oCurrentDateTime;
						}						
						if (typeof oEvent.callback == 'function') {
							oEvent.lastResult	=	oEvent.callback( oEvent );
						}
						if (typeof oTimerOptions.defaultCallback == 'function') {
							oTimerOptions.defaultCallback( oEvent );
						}
					}					
				}				
			}
			$this.userEvents[iEvent] = oEvent;
		}

		/*var refTime = new Date();
						//		year,	mon,	day,		h,		min,	sec,	msec
		var refTimeO = new Date(	2011,	4,		7,		16,		0,		0,		0	);
		var refTimeC = new Date(	2011,	4,		7,		16,		0,		0,		0	);
		*/
		var opened = getNextOpened();
		var closed = getNextClosed();
		
		var oEvent = {};
		oEvent.time = oCurrentDateTime;
		oEvent.opened = opened;
		oEvent.closed = closed;
		oEvent.untilOpened = timeDiff( oCurrentDateTime.getTime(), opened.getTime() );
		oEvent.untilClosed = timeDiff( oCurrentDateTime.getTime(), closed.getTime() );
		
		
		// closed
		if ( (opened.getTime() > oCurrentDateTime.getTime()) && (closed.getTime() > oCurrentDateTime.getDay()) && (opened.getTime() < closed.getTime()) ) {
			onBeforeOpen( oEvent );
		} else {
			onBeforeClose( oEvent );
		}
		
		return ($this);
	};

	function getNextOpened ( timestamp ) {
		if ( (typeof timestamp == 'undefined') ) {
			timestamp	=	new Date();
		}
		var openTime	=	timestamp;
		var iDay		=	timestamp.getDay();
		var dayDiff		=	0;
		var iCount		=	0;
		var iWeekCount	=	0;
		while (openTime.getTime() <= timestamp.getTime()) {
			
			var day			=	days[iDay+dayDiff];

			//console.log(day+ ' - ' +iDay+ ' - ' +dayDiff);
			iCount++;
			if ((iCount % 15) == 0) {
				//if (confirm('abbrechen?')) { break; }
			}
			
			var aTimeSets	=	oSchedule[day];
			if (!aTimeSets) {
				break;
			}
			for ( iSet in aTimeSets ) {
				var setTime = new Date(
					timestamp.getFullYear() ,
					timestamp.getMonth(), 
					timestamp.getDate() + (iWeekCount*7) + dayDiff,  // Math.abs(dayDiff),
					parseInt( String( aTimeSets[iSet][0] ).split(":", 2)[0] ),
					parseInt( String( aTimeSets[iSet][0] ).split(":", 2)[1] ),
					0,
					0
				);
				//console.log(setTime);
				if (setTime.getTime() > timestamp.getTime()) {
					openTime = setTime;
					break;
				}
			}
			if (iDay+dayDiff == 6) {
				dayDiff = iDay * (-1);
				iWeekCount++;
			} else {
				dayDiff++;
			}
		}

		return (openTime);
		
	}
	
	
	function getNextClosed ( timestamp ) {
		if ( (typeof timestamp == 'undefined') ) {
			timestamp	=	new Date();
		}
		var closeTime	=	timestamp;
		var iDay		=	timestamp.getDay();
		var dayDiff		=	0;
		var iCount		=	0;
		var iWeekCount	=	0;
		while (closeTime.getTime() <= timestamp.getTime()) {
			var day			=	days[iDay+dayDiff];

			//console.log(day+ ' - ' +iDay+ ' - ' +dayDiff);
			iCount++;
			if ((iCount % 15) == 0) {
				//if (confirm('abbrechen?')) { break; }
			}
			
			var aTimeSets	=	oSchedule[day];
			if (!aTimeSets) {
				break;
			}
			for ( iSet in aTimeSets ) {
				var setTime = new Date(
					timestamp.getFullYear() ,
					timestamp.getMonth(), 
					timestamp.getDate() + (iWeekCount*7) + dayDiff,
					parseInt( String( aTimeSets[iSet][1] ).split(":", 2)[0] ),
					parseInt( String( aTimeSets[iSet][1] ).split(":", 2)[1] ),
					0,
					0
				);
				//console.log(setTime);
				if (setTime.getTime() > timestamp.getTime()) {
					closeTime = setTime;
					break;
				}
			}
			if (iDay+dayDiff == 6) {
				dayDiff = iDay * (-1);
				iWeekCount++;
			} else {
				dayDiff++;
			}
		}

		return (closeTime);
		
	}
	
	function getDayIntervals ( timestamp ) {
		var iDay = (new Date(timestamp)).getDay();
		/*if (iDay == 0) {
			iDay = 6;
		} else if (iDay == 1) {
			iDay = 0;
		} else {
			iDay -= 1;
		}*/
		var day			=	days[iDay];
		var aTimeSets	=	oSchedule[day];
		return (aTimeSets || []);
	}
	
	// public properties
	$this.userEvents	=	userEvents;
	
	// public methods
	$this.addEvent		=	addEvent;
	$this.removeEvent	=	removeEvent;
	$this.checkEvents	=	checkEvents;
	$this.start			=	startCountdown;
	$this.stop			=	stopCountdown;
	
	$this.getNextOpened	=	getNextOpened;
	$this.getNextClosed	=	getNextClosed;
	$this.getDay		=	getDayIntervals;
	
	init( oOptions );
	
	return ($this);
};

var timeDiff = function ( iStart, iEnd ) {
	var iDiff				=	parseInt(iEnd) - parseInt(iStart);
	var iRest 				= 	iDiff;
	var iYears				=	parseInt ( iRest / 1000 / 60 / 60 / 24 / 365.25 );
	iRest				= 	iRest - (iYears * 365 * 24 * 60 * 60 * 1000);
	var iMonthsDiff			=	parseInt ( iRest / 1000 / 60 / 60 / 24 / (365.25 / 12) ) ;
	iRest				= 	iRest - (iMonthsDiff * 30.417 * 24 * 60 * 60 * 1000);
	var iDaysDiff			=	parseInt ( iRest / 1000 / 60 / 60 / 24 ) ;
	iRest				= 	iRest - (iDaysDiff * 24 * 60 * 60 * 1000);
	var iHoursDiff			=	parseInt ( iRest / 1000 / 60 / 60 ) ;
	iRest				= 	iRest - (iHoursDiff * 60 * 60 * 1000);
	var iMinutesDiff		=	parseInt ( iRest / 1000 / 60 ) ;
	iRest				= 	iRest - (iMinutesDiff * 60 * 1000);
	var iSecondsDiff		=	parseInt ( iRest / 1000 ) ;
	iRest				= 	iRest - (iSecondsDiff * 1000);
	var iMillisecondsDiff	=	parseInt ( iRest );
	
	var oCountdown = {
		years			:	iYears,
		months			:	iMonthsDiff,
		days			:	iDaysDiff,
		hours			:	iHoursDiff,
		minutes			:	iMinutesDiff,
		seconds			:	iSecondsDiff,
		milliseconds	:	iMillisecondsDiff
	};
	return oCountdown;
};

//document.getElementsByTagName(tagname)
/*
var updateClosed = function ( oEvent ) {
	var html = [];
	html.push(
		'Heute leider nicht mehr ge&ouml;ffnet!',
		'<br />',
		'&Ouml;ffnung in ',
		//'<span class="runningtime">',
			//'<span class="left"></span>',
			//'<span class="timenow">',
				((oEvent.untilOpened.hours+(oEvent.untilOpened.days*24) < 10) ? '0' : ''),
				oEvent.untilOpened.hours+(oEvent.untilOpened.days*24), ' : ', 
				((oEvent.untilOpened.minutes < 10) ? '0' : ''),
				oEvent.untilOpened.minutes, ' : ', 
				((oEvent.untilOpened.seconds < 10) ? '0' : ''),
				oEvent.untilOpened.seconds, '',
			//'</span>',
			//'<span class="right"></span>',
		//'</span>',
		''
	);
	document.getElementById(oEvent.target).innerHTML = html.join('');
};



var updateOpened = function ( oEvent ) {
	var html = [];
	html.push(
		'heute noch &ouml;ffnet: ',
		//'<span class="runningtime">',
			//'<span class="left"></span>',
			//'<span class="timenow">',
				((oEvent.untilClosed.hours+(oEvent.untilClosed.days*24) < 10) ? '0' : ''),
				oEvent.untilClosed.hours+(oEvent.untilClosed.days*24), ' : ', 
				((oEvent.untilClosed.minutes < 10) ? '0' : ''),
				oEvent.untilClosed.minutes, ' : ', 
				((oEvent.untilClosed.seconds < 10) ? '0' : ''),
				oEvent.untilClosed.seconds, '',
			//'</span>',
			//'<span class="right"></span>',
		//'</span>',
		''
	);
	document.getElementById(oEvent.target).innerHTML = html.join('');
};



var oCopyshopOpeningCountdown = new openingCountdown({
	autoStart	:	true,
	interval	:	1000,
	clock		:	'countbox',
	schedule	:	{
		monday		:	[ ['9:00', '18:00'] ],
		tuesday		:	[ ['9:00', '18:00'] ],
		wednesday	:	[ ['9:00', '18:00'] ],
		thursday	:	[ ['9:00', '18:00'] ],
		friday		:	[ ['9:00', '18:00'] ],
		saturday	:	[ ['10:00', '14:00'] ],
		sunday		:	[ ]
	},
	onBeforeOpen	:	function ( oEvent ) {
		oEvent.target = 'countbox';
		updateClosed(oEvent);
	},
	onBeforeClose	:	function ( oEvent ) {
		oEvent.target = 'countbox';
		updateOpened(oEvent);
	}

});
var oServiceOpeningCountdown = new openingCountdown({
	autoStart	:	true,
	interval	:	1000,
	clock		:	'countbox',
	schedule	:	{
		monday		:	[ ['9:00', '20:00'] ],
		tuesday		:	[ ['9:00', '20:00'] ],
		wednesday	:	[ ['9:00', '20:00'] ],
		thursday	:	[ ['9:00', '20:00'] ],
		friday		:	[ ['9:00', '20:00'] ],
		saturday	:	[ ['10:00', '16:00'] ],
		sunday		:	[ ]
	},
	onBeforeOpen	:	function ( oEvent ) {
		oEvent.target = 'countbox';
		updateClosed(oEvent);
	},
	onBeforeClose	:	function ( oEvent ) {
		oEvent.target = 'countbox';
		updateOpened(oEvent);
	}

});
*/
