/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */

Calendar = function( input, date, start, end ) {
	Calendar.superClass.apply( this, arguments );
	
	var today = new Date();
	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;
	}

	this.temp = false;
	this.currentDate = false;
	this.selectedDate = false;

	if( date && date instanceof Date ) {
		if( this.start.valueOf() > date.valueOf() ) date = this.start;
		if( this.end.valueOf() < date.valueOf() ) date = this.end;

		this.currentDate = date;
		this.selectedDate = date;
	}
	
	this.lang = ( typeof PageStatus != 'undefined' ? PageStatus.Lang() : 'ru' );
	this.separator = '-';

	var _self = this;
	window.setTimeout( function() {
		_self.init( input, date );
	}, 10 );
}
Calendar.inheritsFrom( Glyph );

/* ----------------------------------------------------------------------- */

Calendar.prototype.init = function( input, date ) {
	this.input = input;
	var _self = this;
	if( !this.input.tpl ) this.input.tpl = 'dd.mm.yyyy';

	this.element = this.createNode( 'div', document.body, {
	    'class': 'cal hidden' + ( PageStatus.Lang() == 'fa' || PageStatus.Lang() == 'id' ? ' ' + 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, 'mousedown', function( params, ev ) {
		this.input.hideCalendar = false;
		this.stopPropagation( ev );
	});

	this.addHandler( document.body, 'mousedown', function( ev ) {
		this.hide();
	});
	
	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 );
	}

	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.setPosition = function() {
	var beacon = this.offset( this.input );
	var offset = this.offset();

	var top = 0;
	var left = 0;

	var rightDelta = beacon[ 'left' ] + 20 + beacon[ 'width' ] + offset[ 'width' ];

	if( rightDelta < window.innerWidth ) {
		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.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.input.hideCalendar = true;
	date = Calendar.dateFormat( this.input.value, this.input.tpl );
	this.changeDate( date );
	this.selectDay( date );
	var _self = this;
	
	window.setTimeout( function() { 
		_self.setClassName( 'hidden', false );

		if( /MSIE (5\.5|6).+Win/.test( navigator.userAgent ) ) {
			_self.setSelects( false );
		}

		_self.setPosition();	
	}, 0 );
}

/* ----------------------------------------------------------------------- */

Calendar.prototype.hide = function() {
	this.setClassName( 'hidden', true );

	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 = this.end.getFullYear(); i >= this.start.getFullYear(); i-- ) {
		var attributes = {
			'value': i
		};

		if(
			date &&
			date.getFullYear &&
			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 ) {
	var msInDay = 1000 * 60 * 60 * 24;
	var firstDayOfMonth = new Date( date.getFullYear(), date.getMonth() );
	var dayOfweek = firstDayOfMonth.getDay();

	if( dayOfweek == 0 && this.lang == 'ru' ) 
		dayOfweek = 7;

	if( this.lang == 'en' ) {
		dayOfweek += 1;
	}

	if( this.lang == 'ar' ) {
		dayOfweek += 2;
	}

	//if( dayOfweek == 7 ) dayOfweek = 0;
	if( dayOfweek == 8 ) dayOfweek = 1;

	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();

	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();
	
	do {
		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 );
			}
		}


		if( currentDate.getMonth() == '9' && currentDate.getDate() == '30' )
            currentDate = new Date( currentDate.valueOf() + msInDay + 60 * 60 * 1000 );		
        else
            currentDate = new Date( currentDate.valueOf() +  msInDay );
	} while( currentDate.getMonth() == new Date( currentDate.valueOf() - msInDay ).getMonth() );
}

/* ----------------------------------------------------------------------- */

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 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;
			day.select( true );
		}
	}

	//InputCalendar.ChangeDate( date );
}

/* ----------------------------------------------------------------------- */

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() {
	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.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.getValue = function() {
	return this.getYear() +
			this.separator + this.toTwoDigits( Number( this.getMonth() ) + 1 ) +
			this.separator + this.toTwoDigits( this.getDate() );
}

/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */

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
		}
	}
})();

// dateFormat sets date to string format, or string to date by set format
Calendar.dateFormat = function () {
	var token = /d{1,2}|[mM]{1,2}|yy(?:yy)?/g,
		mask_default = 'dd.mm.yyyy';
		lang = ( window.PageStatus ? PageStatus.Lang() : ( window.lang ? window.lang : 'ru' ) ),
		pad = function (val, len) {
			val = String(val);
			len = len || 2;
			while (val.length < len) val = '0' + val;
			return val;
		};

	return function ( date, mask ) {
		mask = String( mask || mask_default );

		if( date ) {
			var flags = {
				d : mask.indexOf('dd'),
				m : mask.indexOf('mm'),
				y : mask.indexOf('yyyy')
			};

			if( typeof( date ) === 'string' ) {
				var dateRegular = new Date( Number( date.substr( flags['y'], 4 ) ), date.substr( flags['m'], 2 ) - 1, Number( date.substr( flags['d'], 2 ) ) );
				return dateRegular;
			}
			else if( date instanceof Date ) {
				var _ = 'get',
					d = date[_ + 'Date'](),
					D = date[_ + 'Day'](),
					m = date[_ + 'Month'](),
					y = date[_ + 'FullYear'](),
					flags = {
						d: d,
						dd: pad(d),
						m: m + 1,
						mm: pad(m + 1),
						M: Calendar.config.months[m] ? Calendar.config.months[m]['genitive'].substr(0, 3) : '',
						MM: Calendar.config.months[m] ? Calendar.config.months[m]['genitive'] : '',
						yy: String(y).slice(2),
						yyyy: y
					};

				return mask.replace(token, function ($0) {
					return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
				});
			}
		}

		return false;
	};
}();
