var HHT_DatePickerControllerClass = new Class({
	
	show:function( event, input_id ){
		var input = $( input_id );
		if (input){
			this.checkInitialisation(input);
			input.hht_datepicker.open(event);
		}
	},

	clear:function( event, input_id ){
		var input = $( input_id );
		if (input){
			this.checkInitialisation(input);
			input.hht_datepicker.clear();
		}
	},

	set:function( event, input_id, year, month, day ){
		var input = $( input_id );
		event = new Event(event);
		event.stop();
		if (input){
			this.checkInitialisation(input);

			var date = new Date( year, month-1, day );
			input.hht_datepicker.setDate( date.getTime() );
		}
	},


	setDuration:function( eventm, start_id, stop_id, duration){
		var start = $( start_id );
		var stop  = $( stop_id );
		duration  = parseInt( duration );
		if ( start && stop ){
			this.checkInitialisation(start);
			this.checkInitialisation(stop);
			stop.hht_datepicker.set_duration( duration );
			
		}

	},

	checkInitialisation:function( domItem ){
		if (!domItem.hht_datepicker){
			domItem.hht_datepicker = new HHT_DatePickerClass();
			domItem.hht_datepicker.init(domItem);
		}
	},
	
	selectDateFromSelectBox : function(event, selectBoxId) {
		var selectBox = $(selectBoxId);
		
		if(selectBox) {
		
			var selectedDate = new Date(selectBox.options[selectBox.selectedIndex].value);
		
			if ( node = selectBox.getProperty('hht:datepicker_day_field'    ) ) $(node).value = selectedDate.getDate();
			if ( node = selectBox.getProperty('hht:datepicker_month_field'  ) ) $(node).value = selectedDate.getMonth()+1;
			if ( node = selectBox.getProperty('hht:datepicker_year_field'   ) ) $(node).value = selectedDate.getFullYear();
		}
	}
	
});


var HHT_DatePickerClass = new Class({
	
	debug:function(value){
		// console.debug(value);
	},
	
	init: function(datepicker){
		this.currentTS = 0;
		
		this.debug(['init',datepicker]);
		
		this.datepicker = datepicker;
		this.id = datepicker.getProperty('id');
				
			// load relations
		this.minField       = false;
		if ( node_id = this.datepicker.getProperty('hht:datepicker_min_field'   ) ) {
			this.minField = $(node_id);
			HHT_DatePickerController.checkInitialisation(this.minField);
		}
			
		this.maxField       = false;
		if ( node_id = this.datepicker.getProperty('hht:datepicker_max_field' ) ) {
			this.maxField = $(node_id);
			HHT_DatePickerController.checkInitialisation(this.maxField);
		}
		
		this.durationField  = false;
		this.durationValues = false;
		this.minDuration = 1;
		this.maxDuration = 15;
		if ( node_id = this.datepicker.getProperty('hht:datepicker_dur_field' ) ){
			this.durationField = $(node_id);
			if (this.durationField.getTag() == "select") {
					// getDuration Values from select field
				this.durationValues = new Array();
				var options = $ES( 'option' , this.durationField );
				for (var i= 0;i<options.length; i++ ){
					var option = new Element(options[i]);
					if (option.getProperty('value')){
						this.durationValues.push( parseInt( option.getProperty('value') ) );
					} else {
						this.durationValues.push( parseInt( option.getText() )  );
					}
				}
			 this.minDuration = this.durationValues[0];
			 this.maxDuration = this.durationValues[ this.durationValues.length -1 ];
			} else {
				if ( val  = this.datepicker.getProperty('hht:datepicker_min_duration') ) this.minDuration = parseInt(val);
				if ( val  = this.datepicker.getProperty('hht:datepicker_max_duration') ) this.maxDuration = parseInt(val);
			}
		}
		
			// more relations
		this.dayField   = false;
		this.monthField = false;
		this.yearField  = false;
		if ( node = this.datepicker.getProperty('hht:datepicker_day_field'    ) ) this.dayField    = $(node);
		if ( node = this.datepicker.getProperty('hht:datepicker_month_field'  ) ) this.monthField  = $(node);
		if ( node = this.datepicker.getProperty('hht:datepicker_year_field'   ) ) this.yearField   = $(node);
		
		if (this.durationField && this.durationField.getTag() == "select")	{
			 this.durationValues = new Array();
			 var options = $ES( 'option' , this.durationField );
			 for (var i= 0;i<options.length; i++ ){
			 	var option = new Element(options[i]);
			 	if (option.getProperty('value')){
					this.durationValues.push( parseInt( option.getProperty('value') ) );
				} else {
					this.durationValues.push( parseInt( option.getText() )  );
				}
			 }
			 this.minDuration = this.durationValues[0];
			 this.maxDuration = this.durationValues[ this.durationValues.length -1 ];
		}
					
			// set default options
		this.options = {
			'format':'mm/dd/yyyy',
			'minDate' : null,
			'maxDate' : null,
			'invalid_dates' : null
		};

		if(this.datepicker.getProperty('hht:datepicker_minDate')) {
			this.options['minDate'] = new Date(this.datepicker.getProperty('hht:datepicker_minDate'));
		}

		if(this.datepicker.getProperty('hht:datepicker_maxDate')) {
			this.options['maxDate'] = new Date(this.datepicker.getProperty('hht:datepicker_maxDate'));
		}

		if(this.datepicker.getProperty('hht:datepicker_invalid_dates')) {
			this.options['invalid_dates'] = this.datepicker.getProperty('hht:datepicker_invalid_dates');
		}

			// load language defaults
		var lang = false;	
		if ( html_lang = $$('html').getProperty('lang') )   	lang = html_lang;
		if ( local_lang = this.datepicker.getProperty('lang') ) lang = local_lang;

		this.debug(lang);

		if (lang){
			switch (lang){
				case 'de-DE':
					this.options['format']= 'dd.mm.yyyy';
					this.options['lang']  = 'de-DE';
					break;
				case 'en-UK':
					this.options['format']= 'mm/dd/yyyy';
					this.options['lang']  = 'en-UK';
					break;
			}
		}
			
			// load options from alt tag
		if(this.datepicker.alt) {
			var alt_options = Json.evaluate(this.datepicker.alt);
			for (option in alt_options){
				this.options[option] = alt_options[option];
			}
		}

		this.datepicker.addEvent('focus', this.focus.bindWithEvent( this ) );
		this.datepicker.addEvent('blur', this.blur.bindWithEvent( this ) );
		this.datepicker.addEvent('keypress', this.keypress.bindWithEvent( this ) );
	},
		
	set_duration:function( value ){
		var duration = value;
		var minStr =  this.minField.getValue();
		if (minStr && duration){
			var minTS  = this.date2ts (minStr, this.options.format);
			var newTS  = minTS + 86400000 * duration + 7200000; // last value is 2 h in ms for save day identification
			this.setDate(newTS);
		}
	},
	
	clear:function(){
		this.debug(['clear']);
		this.datepicker.value = '';
	},
	
	repair:function(force){
		var value = this.datepicker.getValue();
		if (value){
			var date_shall    = this.repairDate(value, this.options.format);
			var date_shall_ts = date_shall.getTime();
			if ( date_shall_ts != this.currentTS || force == true ){
				this.setDate(date_shall_ts ); 
			}
		}
	},
	
	focus:function(){
		this.repair(false);
	},
	
	blur:function(){
		if(!this.startEvent || !this.startEvent.target || this.startEvent.target.id != this.datepicker.id) {
			//If we call the date picker directly through the input field
			//the repair function will make the picker unuseable
			this.repair(true);
		}	
	},

	keypress:function(event) {
		if (event.code == 13) {
			this.repair(true);
		}
	},
	
	open:function(event){
		
		this.debug(['open']);

		if(event) {
			this.startEvent = new Event(event);
		}

			// find the entered date, or use the current date
		var value = this.datepicker.getValue();
		
			// current date
		var today = new Date();
		today.setMilliseconds(0);
		today.setSeconds(0);
		today.setMinutes(0);
		today.setHours(0);
		
		if( value != '') {
			var ts = this.date2ts(value, this.options.format);
			var selected_date  = new Date();
			selected_date.setTime(ts);
		} else {
			var selected_date = today;
		}
		
			//save date objects		
		this.options['selected_date'] =  selected_date;
		this.debug([	this.options['selected_date'], this.options.format ]);
		
			// close already running pickers
		if (typeof( hhtActiveDatePicker ) != 'undefined' && hhtActiveDatePicker != false) {
			hhtActiveDatePicker.remove();
			hhtActiveDatePicker = false;
		}
				
			// create picker iframe and inject into page
		this.iframe = new Element( 'iframe', {
			'class'       : 'hht_datepicker_iframe',
			'name'        : 'hht_iframe_' + this.id,
			'scrolling'   : 'no',
			'frameborder' : '0',
			'src'         : '/typo3conf/ext/hht_template/jscripts/hht_datepicker_popup/DatePicker.htm'
		});
		
		this.iframe.injectBefore(this.datepicker);
		
			// add close events on click outside
		document.body.addEvent( 'mousedown', function(){
			this.remove();
			document.body.removeEvents('mousedown');
			
		}.bind(this) );
		
			// save global configuration 
		hhtActiveDatePicker = this;
		
		return; 
	},
	
	setDate:function( dateTS ){

		this.debug(['setDate',dateTS, this.datepicker]);
		var duration = false;

			// handle this.minField this.minDuration this.maxDuration
		if ( $(this.minField)  ){
			var minStr =  $(this.minField).getValue();
			if (minStr){
				var minTS  = this.date2ts (minStr, this.options.format );
				duration   = this.validateDuration( Math.round( (dateTS - minTS )/86400000 ) )
			} else {
				duration   = this.validateDuration( 0 );
			}
			this.minField.hht_datepicker.set( dateTS - (duration * 86400000 ) + (7200000) ); // last value is 2 h in ms for save day identification
		}
		
			// handle max field
		if ( $(this.maxField)  ){
			if (  this.durationField && this.durationField.getValue() ){
				duration = parseInt( this.durationField.getValue() );
			} else {
				var maxStr     = $(this.maxField).getValue();
				var lastString = this.datepicker.getValue();
				if (maxStr){
					var maxTS  = this.date2ts ( maxStr,     this.options.format);
					var lastTS = this.date2ts ( lastString, this.options.format);
					duration   = this.validateDuration( Math.round( (maxTS - lastTS)/86400000 ) )
				} else {
					duration   = this.validateDuration( 0 );
				}
			}
			this.maxField.hht_datepicker.set( dateTS + (duration * 86400000) + (7200000) ); // last value is 2 h in ms for save day identification
		}	
		
			// update duration field
		if ( this.durationField && duration ){
			if (this.durationField.getValue() != duration){
				this.durationField.value = duration;
				this.durationField.fireEvent( 'change', {target:this.durationField, type:'change'} , 0 );
			}
		}
		 
			// save Data
		this.set(dateTS);
			
			/* trigger callback */
		if ( this.options.callback ){
			var cb = eval( this.options.callback ) ;
			if (cb){
				cb(dp);
			} 
		}
		
			// remove picker
		this.remove();	
	},

	setDateYMD:function(year, month, day){
		var date = new Date(  parseInt(year), parseInt(month)-1, parseInt(day) );
		return ( this.setDate (date.getTime()) );
	},
	
	validateDuration:function(duration){
			// handle min and max
		if (duration < this.minDuration){
			return this.minDuration;
		}
		if (duration > this.maxDuration){
			return  this.maxDuration;
		}
			// get next from duration values if optins array is present
		if (this.durationValues.length>1){
			return duration;
		} else {
			return duration;
		}
	},
	
	set:function (dateTS){
			// format and update value
		if (this.currentTS != dateTS){
				// save local TS
			var formated_date = this.ts2date( dateTS , this.options.format );
			this.datepicker.value  = formated_date;
		}
		
			// set day_field month and year fields
		var date = new Date();
		date.setTime(dateTS);	
		
		if (this.dayField){
			var val = date.getDate();
			if (this.dayField.getValue() != val){
				this.dayField.value = val;
			}
		}
		
		if (this.monthField){
			var val = 1+date.getMonth();
			if (this.monthField.getValue() != val){
				this.monthField.value = val;
			}
		}
		
		if (this.yearField){
			var val = date.getFullYear();
			if (this.yearField.getValue() != val){
				this.yearField.value = val;
			}
		}
		
			// fire update event
		if ( this.currentTS != dateTS ){
			this.datepicker.fireEvent( 'change', {target:this.datepicker, type:'change'} , 0 );
			this.currentTS = dateTS;
		}
		
	},
	
	getTS:function(){
		return this.currentTS;
	},
	
	remove:function(){
			// remove iframe
		if (this.iframe){
			this.iframe.remove();
			this.iframe = false;
		}
			// remove global reference
		if ( typeof( hhtActiveDatePicker ) != 'undefined' && hhtActiveDatePicker && hhtActiveDatePicker == this){
			hhtActiveDatePicker = false;
		}
	},
	
		/* 
		 * the following methods are date helper methods 
		 * copied from the hht:date_helper.js class
		 */
		
	
	repairDate:function(value, format ){

		/* replace splitting chars in format and date string */
		var v = value.replace (/[\D]+/g, ":"); //all non numbers are delimiters
		var f = format.replace(/[\W]+/g, ":"); //all non alphanum  chats are delimiters 
		
		/* split format and value */
		var v_parts = v.split(':');
		var f_parts = f.split(':');

		/* default = now */
		var now   = new Date();
		now.setMilliseconds(0);
		now.setSeconds(0);
		now.setMinutes(0);
		now.setHours(0);
		
		/* empty values */
		var year  = Number.NaN;
		var month = Number.NaN;
		var day   = Number.NaN;


		if(this.options['minDate']) {
			/* minDate */
			var minDate = this.options['minDate'];
		}else {
			var minDate = null;
		}

		if(this.options['maxDate']) {
			/* maxDate */
			var maxDate = this.options['maxDate'];
		}else {
			this.maxDate = null;
		}

		for ( var key = 0; key< f_parts.length ; key ++){
			
			var p_value  = "" + v_parts[key];
			var p_format = "" + f_parts[key];
				
			if ( p_value ){
				
					// remove leading zeros
				p_value = p_value.replace (/^[0]+/g, '' );
	
				switch (p_format ){
					case 'yyyy':
						year  = parseInt(p_value);
						break;
					case 'mm':
						month = parseInt(p_value);
						break;
					case 'dd':
						day   = parseInt(p_value);
						break;
				}
			}
		}
		
		/* fix date value */
		if ( isNaN(day) || day > 31 ){
			day = now.getDate();
		}
		
		/* fix month value */
		if ( isNaN(month) || month > 12 ) {
			if (day >= now.getDate() ) {
				month = 1 + now.getMonth(); // this month
			} else {
				month = 2 + now.getMonth(); // next month
			}		
		}
		
		/* fix present year values */
		if ( !isNaN(year) ) {
			if (year < 100 ) year = 2000 + year;
			if  ( year < now.getFullYear() || year > now.getFullYear() + 5 ) {
				if ( (month > now.getMonth() + 1) || ( month == now.getMonth() + 1 && day > now.getDate() ) ){
					year = now.getFullYear();				
				} else {
					year = now.getFullYear() + 1;
				}
			}
		}
		
		/* guess empty year values */
		if  ( isNaN(year) ) {
			if ( (month > now.getMonth() + 1 || ( month == now.getMonth() +1 && day >= now.getDate() ) ) ) {
				year = now.getFullYear();
			} else {
				year = now.getFullYear() + 1 ;
			} 
		}
		
		/* format value */
		var corrected_date = new Date(year, ( month-1 ), day);

		if(minDate != null && minDate > corrected_date) {
			corrected_date = minDate;
		}

		if(maxDate != null && maxDate < corrected_date) {
			corrected_date = maxDate;
		}

		if (corrected_date < now){
			return now;
		} else {
			return corrected_date;
		}
	},
		
		/* Convert Date-Str to JS-Timestamp */
		
	date2ts:function(dateStr,format){

			// default value
		var now = new Date();  
		var year   = now.getFullYear()  ;
		var month  = now.getMonth() ;
		var day    = now.getDate();

			// extract y m d from date-str
		var dd = this.extractDatePart(format, dateStr, 'dd');
		while (dd.substr(0,1) == '0') dd = dd.substr(1);			
		if (dd)	 day = parseInt(dd);

		var mm = this.extractDatePart(format, dateStr, 'mm' );
		while (mm.substr(0,1) == '0') mm = mm.substr(1);	
		if (mm)	 month =  parseInt(mm) -1;

		var yyyy = this.extractDatePart(format, dateStr, 'yyyy' );
		while (yyyy.substr(0,1) == '0') yyyy = yyyy.substr(1);	
		if (yyyy)  year =  parseInt(yyyy);
		
			// convert values
		var date = new Date( year, month, day);
		
		return ( date.getTime() );
	},
	
	ts2date:function(ts,format){
	
		var date = new Date();
		date.setTime(ts);
		
		var year   = date.getFullYear()  ;
		var month  = date.getMonth() + 1 ;
		var day    = date.getDate() ;
		
		if (day < 10) day = '0' + day;
		if (month < 10) month = '0' + month;
		var dateStr = format.replace( /dd/i, day ).replace( /mm/i, month ).replace( /yyyy/i, year );
		
		return dateStr;
	},
	
	extractDatePart:function(format, string, pattern){
		var result = "";
		var start = format.indexOf(pattern);
		var len   = pattern.length; 
		if (start > -1 && len > 0 ){
			result = string.substr(start, len);
		}
		return result;
	}
	
});

var HHT_DatePickerController = new HHT_DatePickerControllerClass();

