/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */

Calendar = function( input, date, start, end ) {
	Calendar.superClass.apply( this, arguments );

	var today = new Date();
	if( window.now_datetime ) {
		var temp_parts = window.now_datetime.split( ' ' );
		if(
			temp_parts &&
			temp_parts instanceof Array &&
			temp_parts.length == 2
		) {
			var temp_date = temp_parts[ 0 ].split( '.' );
			var temp_time = temp_parts[ 1 ].split( ':' );
			today = new Date( temp_date[ 2 ], temp_date[ 1 ] - 1, temp_date[ 0 ], temp_time[ 0 ], temp_time[ 1 ] );
		}
	}
	this.days = new Array();
	this.selects = document.getElementsByTagName( 'SELECT' );

	if(
		!start ||
		!( start instanceof Date )
	) {
		this.start = new Date( ( today.getFullYear() - 90 ), today.getMonth(), today.getDate() );
	} else {
		this.start = start;
	}

	if(
		!end ||
		!( end instanceof Date )
	) {
		this.end = today;
	} else {
		this.end = end;
	}

	if( 
		date &&
		date instanceof Date
	) {
		if( this.start.valueOf() > date.valueOf() ) date = this.start;
		if( this.end.valueOf() < date.valueOf() ) date = this.end;
	}

	this.temp = false;
	this.currentDate = false;
	this.selectedDate = false;

	this.lang = lang = ( window.PageStatus ? PageStatus.Lang() : ( window.lang ? window.lang : 'ru' ) );;
	this.separator = '-';
	
	var _self = this;
	window.setTimeout( function() {
		_self.init( input, date );
	}, 0 );

	return this;
}
Calendar.inheritsFrom( Glyph );

/* ----------------------------------------------------------------------- */

Calendar.prototype.init = function( input, date ) {
	this.input = this.getEl( input );
	if(
		!this.input ||
		this.input.nodeName != 'INPUT' ||
		this.input[ 'type' ] != 'text'
	) return false;

	this.visible = this.createNode(
		'input',
		false,
		{
			'class': this.input.className + ' calInput',
			'type': 'text',
			'id': 'vis_' + this.input[ 'id' ],
			'name': 'vis_' + this.input[ 'name' ],
			'readonly': 'readonly'
		}
	);

	var inputStyle = this.input.getAttribute( 'style' );
	if( inputStyle ) {
		if( typeof inputStyle  == 'object' ) 
			this.visible.style.cssText = inputStyle.cssText;
		else 
			this.visible.setAttribute('style', inputStyle );
	}
	this.input.parentNode.insertBefore( this.visible, this.input );
	this.input.style[ 'display' ] = 'none';

	this.element = this.createNode( 'div', document.body, {
	    'class': 'cal hidden' + ( PageStatus.Lang() == 'ir' || PageStatus.Lang() == 'fa' ? ' ' + PageStatus.Lang() : '' )
    });
	this.controlsWrap = this.createNode( 'div', this.element, { 'class': 'controls' });

	this.year = this.createNode( 'select', this.controlsWrap, { 'class': 'year' });
	this.month = this.createNode( 'select', this.controlsWrap, { 'class': 'month' });

	var weekWrap = this.createNode( 'div', this.element, { 'class': 'week' });

	for( var c in Calendar.config.daysOfWeek ) {
		this.createNode( 'div', weekWrap, false, Calendar.config.daysOfWeek[ c ][ 'short' ] );
	}

	this.daysWrap = this.createNode( 'div', this.element, { 'class': 'days' });

	this.addHandler( this.element, 'click', function( params, ev ) {
		this.stopPropagation( ev ); 
	});

	this.addHandler( this.visible, 'click', this.planShow );
	this.addHandler( this.visible, 'keydown', this.onKeyDown );

	if(
		new RegExp( /^\d{4}-\d{2}-\d{2}$/ ).test( this.input.value )
	) {
		var d = this.input.value.split( '-' );
		date = new Date( Number( d[0] ), Number( d[1] ) - 1, Number( d[2] ) );
	}

	
	if(
		!date ||
		!( date instanceof Date )
	) {
		var chDate = new Date();
		if( 
			this.end &&
			this.end.valueOf() < chDate.valueOf()
		) {
			chDate = this.end;
		}
		
		if(
			this.start &&
			this.start.valueOf() > chDate.valueOf()
		) {
			chDate = this.start;
		}
		
		this.createYears( chDate );
		this.changeDate( chDate );
	} else {
		this.createYears( date );
		this.changeDate( date );
		this.selectDay( date );
	}

	if(
		date &&
		date instanceof Date
	) {
		this.setInput();
	}

	this.addHandler( this.year, 'change', this.onYearChange );
	this.addHandler( this.year, 'keyup', this.onYearChange );
	this.addHandler( this.month, 'change', this.onMonthChange );
	this.addHandler( this.month, 'keyup', this.onMonthChange );

	this.addHandler( window, 'resize', this.setPosition );
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.planShow = function( params, ev ) {
	var _self = this;
	window.setTimeout( function() { 
		_self.show();
		_self.setPosition();
	}, 0 );
	this.preventDefault( ev );
}

/* ----------------------------------------------------------------------- */

// календарь с ограниченной датой "с"
Calendar.prototype.setCalendarStart = function( calendar ) {
	this.calendar_start = calendar;
}

// календарь с ограниченной датой "до" 
Calendar.prototype.setCalendarEnd = function( calendar ) {
	this.calendar_end = calendar;
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.setPosition = function() {
	var beacon = this.offset( this.visible ),
		offset = this.offset(),
		top = 0,
		left = 0,
		rightDelta = beacon[ 'left' ] + 20 + beacon[ 'width' ] + offset[ 'width' ],
		body_width = document.compatMode=='CSS1Compat' && !window.opera?document.documentElement.clientWidth:document.body.clientWidth;

	if( this.lang == 'ar' || this.lang == 'fa' ) {
		if( beacon['left'] < offset[ 'width' ] ) {
			top = beacon[ 'top' ] + beacon[ 'height' ] + 5 + 'px';
			left = beacon[ 'left' ] + 'px';
		}
		else {
			top = beacon[ 'top' ] - 10 + 'px';
			left = beacon[ 'left' ] - 10 - offset[ 'width' ] + 'px';
		}
	} else if( rightDelta < body_width ) {
		top = beacon[ 'top' ] - 10 + 'px';
		left = beacon[ 'left' ] + 10 + beacon[ 'width' ] + 'px';
	} else {
		top = beacon[ 'top' ] + beacon[ 'height' ] + 5 + 'px';
		left = beacon[ 'left' ] + beacon[ 'width' ] - offset[ 'width' ] + 'px';
	}
	
	this.setStyle({
		'top': top,
		'left': left
	});
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.onKeyDown = function( params, ev ) {
	ev = ev || window.event;
	var code = ev.charCode || ev.keyCode;
	if( ev.ctrlKey || ev.altKey ) return true;
	
	if(
		code == 8 ||
		code == 46
	) {
		this.input.value = '';
		this.visible.value = '';
	}
	
	this.preventDefault( ev );
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.setSelects = function( flag ) {
	for( var i = this.selects.length; i; i-- ) {
		var select = this.selects[ i - 1 ];
		if(
			select &&
			select.style &&
			select != this.year &&
			select != this.month
		) {
			this.setStyle({
				'visibility': flag ? 'visible' : 'hidden'
			}, select );
		}
	}
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.show = function() {
	this.setClassName( 'hidden', false );
	this.setClassName( 'active', true, this.visible );
	this.setClassName( 'active', true, this.visible.parentNode );
	this.addHandler( document.body, 'click', this.hide );
	
	this.temp = this.getValue();
	if( /MSIE (5\.5|6).+Win/.test( navigator.userAgent ) ) {
		this.setSelects( false );
	}
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.hide = function() {
	this.setClassName( 'hidden', true );
	this.setClassName( 'active', false, this.visible );
	this.setClassName( 'active', false, this.visible.parentNode );
	this.removeHandler( document.body, 'click', this.hide );

	//if( this.temp !== this.getValue() ) {
		//this.notify( 'Changed' );
	//}
	
	if( /MSIE (5\.5|6).+Win/.test( navigator.userAgent ) ) {
		this.setSelects( true );
	}
}

/* --------------------------------------------- Create Years ------------------------------------------------- */

Calendar.prototype.createYears = function( date ) {
	if( !this.year ) return false;

	this.setContent( '', this.year );

	for( var i = Number( this.end.getFullYear() ); i >= Number( this.start.getFullYear() ); i-- ) {
		var attributes = {
			'value': i
		};

		if(
			date &&
			date.getFullYear &&
			Number( date.getFullYear() ) == i
		) {
			attributes[ 'selected' ] = 'selected';
		}

		this.createNode( 'option', this.year, attributes, i.toString() );
	}
}

/* --------------------------------------------- Create Months ------------------------------------------------ */

Calendar.prototype.createMonths = function( date ) {
	if(
		!date ||
		!( date instanceof Date ) || 
		!this.month
	) return false;

	this.setContent( '', this.month );

	var year = date.getFullYear();
	var first = 0;
	var last = 11;
	
	var firstDay = new Date( date.getFullYear(), date.getMonth() );
	var lastDay = new Date( date.getFullYear(), date.getMonth() + 1, -1 );

	if( year == this.start.getFullYear() ) {
		first = Number( this.start.getMonth() );
	}

	if( year == this.end.getFullYear() ) {
		last = Number( this.end.getMonth() );
	}

	for( var c = first; c <= last; c ++ ) {
		var attributes = {
			'value': c
		};

		if( date && date.getMonth && ( date.getMonth() == c || ( c == 0 && last < date.getMonth() ) ) ) {
			attributes[ 'selected' ] = 'selected';
		}

		this.createNode( 'option', this.month, attributes, Calendar.config.months[ c ][ 'nominative' ] );
	}
}

/* ---------------------------------------------- Create Days ------------------------------------------------- */

Calendar.prototype.createDays = function( date ) {
    if( !date )
        return false;

	var msInDay = 1000 * 60 * 60 * 24;
	var firstDayOfMonth = new Date( date.getFullYear(), date.getMonth() );
	var dayOfweek = firstDayOfMonth.getDay();
	
	if( dayOfweek == 0 && ( this.lang != 'en' ) ) 
		dayOfweek = 7;

	if( this.lang == 'en' ) {
		dayOfweek += 1;
	}

	if( this.lang == 'ar' ) {
		dayOfweek += 2;
	}

	//if( dayOfweek == 7 ) dayOfweek = 0;
	if( dayOfweek == 8 ) dayOfweek = 1;
	
	
	this.removeDays();

	for( var i = 0; i < dayOfweek - 1; i++ ) {
		this.createNode( 'div', this.daysWrap, { 'class': 'empty' });
	}

	var currentDate = firstDayOfMonth;
	var curYear = currentDate.getFullYear();
	var curMonth = currentDate.getMonth();
	
	while( firstDayOfMonth.getMonth() === currentDate.getMonth() ) {
		var day = this.addDay( currentDate );
		if(
			day &&
			day.disable
		) {
			if(
				curYear == this.start.getFullYear() &&
				curMonth == this.start.getMonth() &&
				currentDate.getDate() < this.start.getDate()
			) {
				day.disable( true );
			}

			if(
				curYear == this.end.getFullYear() &&
				curMonth == this.end.getMonth() &&
				currentDate.getDate() > this.end.getDate()
			) {
				day.disable( true );
			}
		}

    currentDate = new Date( currentDate.valueOf() + msInDay );
	} 
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.removeDays = function() {
	for( var c = this.days.length; c; c-- ) {
		var day = this.days[ c - 1 ];
		day.detachObserver( 'Choosed', function( params, day ) {
			this.selectDate( day.getDate() );
			this.hide();
		}, this );
		day.remove();
	}

	this.setContent( '', this.daysWrap );
	this.days = new Array();
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.onYearChange = function() {
	var value = this.getYear();
    var newDate = new Date( new Date( this.currentDate.valueOf() ).setYear( value ) );
	this.changeDate( newDate );

    this.onMonthChange();

	if( this.selectedDate ) {
		this.selectDay( newDate );
	}
}

/* ----------------------------------------------------------------------- */

/*Calendar.prototype.onMonthChange = function() {
	var value = this.getMonth();

	var newDate = new Date( new Date( this.currentDate.valueOf() ).setMonth( value ) );
	//this.changeDate( newDate );
	this.currentDate = newDate;
	this.createDays( newDate );
	if( this.selectedDate ) {
		this.selectDay( newDate );
	}
}*/
Calendar.prototype.onMonthChange = function() {
	var value = this.getMonth();

    var testDate = new Date( new Date( this.currentDate.valueOf() ).setMonth( value ) );
    if( testDate.getMonth() == value )
        var newDate = testDate;
    else {
        newDate = new Date( new Date( this.currentDate.valueOf() ).setDate( 1 ) );
        newDate.setMonth( value );
    }

	//this.changeDate( newDate );
	this.currentDate = newDate;
	this.createDays( newDate );
	if( this.selectedDate ) {
		this.selectDay( newDate );
	}
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.changeDate = function( date ) {
	this.currentDate = date;
	//this.createYears( date );
	this.createMonths( date );
	this.createDays( date );
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.selectDay = function( date ) {
	for( var c in this.days ) {
		var day = this.days[ c ];
		if(
			day &&
			day.date &&
			day.date instanceof Date &&
			date &&
			date.getFullYear() == day.date.getFullYear() &&
			date.getMonth() == day.date.getMonth() &&
			date.getDate() == day.date.getDate()
		) {
			this.selectedDate = date;

            //if( /test1|localhost/.test( document.location.href ) ) {
                if( this.calendar_end ) {
                    this.calendar_end.start = this.selectedDate;
                    this.calendar_end.createYears( this.calendar_end.currentDate );
                    this.calendar_end.changeDate( this.calendar_end.currentDate );
                }
                if( this.calendar_start ) {
                    this.calendar_start.end = this.selectedDate;
                    this.calendar_start.createYears( this.calendar_start.currentDate );
                    this.calendar_start.changeDate( this.calendar_start.currentDate )
                }
            //}

			day.select( true );
		}
	}
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.getYear = function() {
	if( this.year && this.year.value ) return this.year.value;
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.getMonth = function() {
	if( this.month && this.month.value ) return this.month.value;
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.getDate = function() {
	if(
		!this.selectedDate ||
		!this.selectedDate.getDate
	) return false;
	
	return this.selectedDate.getDate();
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.setYear = function( date ) {
	var year = Number( date.getFullYear() );
	var options = this.years.getElementsByTagName( 'OPTIONS' );
	for( var i = options.length; i; i-- ) {
		var option = options[ i - 1 ];
		if( option.hasAttribute( 'selected') ) {
			option.removeAttribute( 'selected' );
		}
		option.selected = false;
		
		if( option[ 'value' ] + '' == year + '' ) {
			option.setAttribute( 'selected', 'selected' );
			option.selected = true;
		}
	}
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.setMonth = function( date ) {
	var month = Number( date.getMonth() );
	var options = this.month.getElementsByTagName( 'OPTIONS' );
	for( var i = options.length; i; i-- ) {
		var option = options[ i - 1 ];
		if( option.hasAttribute( 'selected') ) {
			option.removeAttribute( 'selected' );
		}
		option.selected = false;
		
		if( option[ 'value' ] + '' == month + '' ) {
			option.setAttribute( 'selected', 'selected' );
			option.selected = true;
		}
	}
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.addDay = function( date ) {
	if( !date || !( date instanceof Date ) ) return false;
	var day = new CalendarDay( this.daysWrap, date );
	this.days[ this.days.length ] = day;
	
	day.attachObserver( 'Choosed', function( params, day ) {
		this.selectDate( day.getDate() );
		this.hide();
	}, this );
	return day;
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.selectDate = function( date ) {
	this.changeDate( date );
	this.selectDay( date );
	this.setInput();
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.toTwoDigits = function( num ) {
	if(
		Number( num ) < 10 &&
		Number( num ) > 0
	) return '0' + num;
	return num + '';
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.setInput = function() {
	var year = this.getYear();
	var month = Calendar.config.months[ this.getMonth() ][ 'genitive' ];
	var day = this.getDate()

	if(
		this[ this.lang + 'Formate' ] &&
		this[ this.lang + 'Formate' ] instanceof Function
	) {
		var value = this[ this.lang + 'Formate' ]( day, month, year );
	} else {
		var value = this.ruFormate( day, month, year );
	}

	this.visible[ 'value' ] = value;

	this.input.value = this.serverFormate( this.getDate(), this.getMonth(), this.getYear() );

	if( document.createEvent ) {
		var ev = document.createEvent( 'UIEvents' );
		ev.initEvent( "change", false, false );
		this.input.dispatchEvent( ev );
	} else if( document.createEventObject ) {
		var ev = document.createEventObject();
		this.input.fireEvent( 'onchange', ev );
	}

	this.notify( 'Changed' );
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.serverFormate = function( day, month, year ) {
	return year +
			this.separator + this.toTwoDigits( Number( month ) + 1 ) +
			this.separator + this.toTwoDigits( day );
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.enFormate = function( day, month, year ) {
	return month + ' ' + day + ' ' + year + '';
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.ruFormate = function( day, month, year ) {
	return day + ' ' + month + ' ' +year + '';
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.esFormate = function( day, month, year ) {
	return day + ' de ' + month + ' del ' + year + '';
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.cnFormate = function( day, month, year ) {
	return year + '年' + month + '' + day + '日';
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.frFormate = function( day, month, year ) {
	return day + ' ' + month + ' ' +year + '';
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.arFormate = function( day, month, year ) {
	return day + ' ' + month + ' ' +year + '';
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.getValue = function() {
	return	this.getYear() +
			this.separator + this.toTwoDigits( Number( this.getMonth() ) + 1 ) +
			this.separator + this.toTwoDigits( this.getDate() );
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.remove = function() {
	this.removeDays();

	this.removeHandler( this.visible, 'click', this.planShow );
	this.removeHandler( this.visible, 'keydown', this.onKeyDown );

	this.removeHandler( this.year, 'change', this.onYearChange );
	this.removeHandler( this.year, 'keyup', this.onYearChange );
	this.removeHandler( this.month, 'change', this.onMonthChange );
	this.removeHandler( this.month, 'keyup', this.onMonthChange );

	this.removeHandler( window, 'resize', this.setPosition );
	this.element.parentNode.removeChild( this.element );
}

/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */

CalendarDay = function( target, date ) {
	CalendarDay.superClass.apply( this, arguments );
	this.date = date;
	this.disabled = false;

	this.element = this.createNode( 'div', target, { 'class': 'day' }, date.getDate() + '' );
	this.addHandler( this.element, 'mouseover', this.setHover, true );
	this.addHandler( this.element, 'mouseout', this.setHover, false );
	this.addHandler( this.element, 'click', this.choose );
}
CalendarDay.inheritsFrom( Glyph );

/* ----------------------------------------------------------------------- */

CalendarDay.prototype.disable = function( flag ) {
	this.disabled = flag;
	this.setClassName( 'disabled', flag );
	this.setProperty({
		'disabled': flag
	});
}

/* ----------------------------------------------------------------------- */

CalendarDay.prototype.choose = function() {
	if( this.disabled ) return false;
	this.notify( 'Choosed' );
}

/* ----------------------------------------------------------------------- */

CalendarDay.prototype.isDisabled = function() {
	return this.disabled;
}

/* ----------------------------------------------------------------------- */

CalendarDay.prototype.setHover = function( flag ) {
	if( this.disabled ) return false;
	this.setClassName( 'hover', flag );
}

/* ----------------------------------------------------------------------- */

CalendarDay.prototype.remove = function() {
	this.removeHandler( this.element, 'mouseover', this.setHover, true );
	this.removeHandler( this.element, 'mouseout', this.setHover, false );
	this.removeHandler( this.element, 'click', this.choose );
	this.element.parentNode.removeChild( this.element );
}

/* ----------------------------------------------------------------------- */

CalendarDay.prototype.getDate = function() {
	return this.date;
}

/* ----------------------------------------------------------------------- */

CalendarDay.prototype.select = function( flag ) {
	if( this.disabled ) return false;
	this.setClassName( 'selected', flag );
}

/* ----------------------------------------------------------------------- */

Calendar.config = (function() {
	if( typeof _text == 'function' ) {
		var months = [ 'JANUARY', 'FEBRUARY', 'MARCH', 'APRIL', 'MAY', 'JUNE', 'JULY', 'AUGUST', 'SEPTEMBER', 'OCTOBER', 'NOVEMBER', 'DECEMBER' ],
			days = [ 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY' ],
			months_result = [],
			days_result = [],
			c,
			lang = ( window.PageStatus ? PageStatus.Lang() : ( window.lang ? window.lang : 'ru' ) );

		if( lang == 'en' ) {
			days.unshift( days.pop() );
		}
		if( lang == 'ar' ) {
			days.unshift( days.pop() );
			days.unshift( days.pop() );
		}

		for( c in months ) {
			months_result.push({
				genitive : _textLight( 'CALENDAR_' + months[c] + '_GENITIVE' ),
				nominative : _textLight( 'CALENDAR_' + months[c] + '_NOMINATIVE' )
			});
			if( !months_result[months_result.length - 1].genitive )
				months_result[months_result.length - 1].genitive = months_result[months_result.length - 1].nominative;
		}
		for( c in days ) {
			days_result.push({
				'long' : _text( 'CALENDAR_' + days[c] ),
				'short' : _text( 'CALENDAR_' + days[c] + '_SHORT' )
			});
		}

		return {
			months : months_result,
			daysOfWeek : days_result
		}
	}
})();
