// -------------------------------------------------------------------------- //
// ------------------------------ Calendar ---------------------------------- //
// -------------------------------------------------------------------------- //

function getLength( obj ){
	var len = 0;
	for ( prop in obj ){
		len++;
	}
	return len;
}

function getLastNumberOfDate( obj ){
	var arr = new Array();
	for ( prop in obj ){
		arr.push( prop );
	}
	arr.sort();
	return arr[ arr.length - 1];
}

var dayHeight = 24;
var dayWidth = 36;

var Calendar = function( target, start, end ) {
	Calendar.superClass.apply( this, arguments );

	this.Id = 'Calendar';
	this.start = start || now;
	this.end = end;

	//this.monthsToStrList = [ 'янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек' ];
	//this.monthsListGC = [ 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря' ];
	//this.weekdaysList = [ 'воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота' ];
	this.length = ( end.valueOf() - start.valueOf() ) / 1000 / 60 / 60 / 24;
	this.avToSelect = 0;
	//this.status = false;
	//this.errMsgs = ( errMsg instanceof Array ) ? errMsg : new Array();

	//this.drag = drag;

	//this.arrChosenDays = new Array();
	this.arrChosenDays = new Object();		// выбранные даты

	this.element = target;
	this.inner = this.element.firstChild;

	//this.monthsList = new Array();

	this.elementDaysWrap = this.getEl( 'days-wrap' );
	this.elementDays = this.inner.childNodes[2].firstChild;
	//this.arrAllDays = $('#days div.month-block .month-days div[class!=empty][class!=month]');
	this.arrAllDays = $('#days td[class!=empty][class!=month]');
	for ( var i = 0; i < this.arrAllDays.length; i++ ){
		this.arrAllDays[ i ].setAttribute( 'idx', i );
	}
	this.hovered = false;

	var curDay = this.start.getDay();
	if( curDay == 0 ) {
		curDay = 7;
	}
	var i = 0;
	while( curDay > i + 1 ) {
		i++;
	}
	this.emptyDays = i;

	this.period = false;

	if( this.length + this.emptyDays > 56 ) {
		if ( $.browser.mozilla ){
			this.addHandler( this.elementDaysWrap, 'DOMMouseScroll', this.scroll );
		}
		else {
			this.addHandler( this.elementDaysWrap, 'mousewheel', this.scroll );
		}
	}

	
	//Hover effect
	this.arrAllDays.mouseover( function(){
		if ( !($(this).hasClass('na') ||  $(this).hasClass('day0')) ) $(this).addClass('hover');
	})
	.mouseout( function(){
		$(this).removeClass('hover');
	});
	
	//Hover buttons
	$('#calendar-wrap .cSlider').mouseover(function(){
		var curTopPos = parseInt( $('#calendar-wrap #days').css('top') ) * ( -1 );
		var elDays = $('#calendar-wrap #days');
		var blockHeight = $('#days-wrap').height();
		if(	( curTopPos == 0 && $(this).attr('id') == 'cUp' ) ||
			( ( curTopPos == elDays.height() - blockHeight || blockHeight - elDays.height() > 0 ) && $(this).attr('id') == 'cDown' ) ) {
			//var a = false;
		}
		else {
			$(this).addClass('hover');
		}
	}).mouseout(function(){
		$(this).removeClass('hover');
	});
	
	//Scroll on click
	$('#calendar-wrap .cSlider').click(function(){
		var elDays = $('#calendar-wrap #days');
		var blockHeight = $('#days-wrap').height();
		var curTopPos = parseInt( elDays.css('top') ) * ( -1 );
		if(	( curTopPos == 0 && $(this).attr('id') == 'cUp' ) ||
			( ( curTopPos == elDays.height() - blockHeight || blockHeight - elDays.height() > 0 ) && $(this).attr('id') == 'cDown' ) ) {
			//var a = false;
		}
		else {
			var dir = ($(this).attr('id') == 'cUp') ? -1 : 1;
			var months = $('#days tr.newMonth');
			var curMonth = months.length - 1;
			for ( var i = 0, len = months.length; i < len - 1; i++ ){
				if ( curTopPos >= months[ i ].offsetTop &&
					curTopPos < months[ i + 1 ].offsetTop ) {
					curMonth = i;
				}
			}
			if ( curMonth + dir  >= 0 && curMonth + dir < months.length ){
				var newTopPos = months[ curMonth + dir ].offsetTop;
				var diffBlockAndContent = elDays.height() - blockHeight;
				if ( diffBlockAndContent > 0 && newTopPos > diffBlockAndContent ) newTopPos = diffBlockAndContent;
				//if ( newTopPos < elDays.height() ){
					elDays.animate({'top': newTopPos * ( -1 ) + 'px'}, 500, 'linear');
				//}
			}
		}
	});
	
	this.addHandler( this.elementDays, 'click', this.getSelectDate );
}
Calendar.inheritsFrom( HTMLGlif );


// ----------------------- Calendar Change Mode ----------------------------- //
// если изменилось количество городов
Calendar.prototype.changeMode = function( iCount ) {
	iCount = iCount || 0;
	if( typeof( iCount ) != 'number' ) return;
	this.avToSelect = iCount;
	if( getLength( this.arrChosenDays ) > this.avToSelect ) {		// очищаем даты удаленных перелетов
		this.clear( getLength( this.arrChosenDays ) - this.avToSelect );
	}
	this.setStatus();	//внешний вид всего блока
	this.setNAdates();	//до выбранной даты присваиваем класс na
	this.setPeriod();	//раскрашиваем период
	//this.check();
}

// -------------------------------------------------------------------------- //
// при клике на дату вызываем эту функцию
Calendar.prototype.getSelectDate = function( params, ev ) {
	var el = ev.target || ev.srcElement;
	var elTD = el.parentNode;
	// проверка на клик после предыдущей даты
	if( this.avToSelect > 1 && this.avToSelect > getLength( this.arrChosenDays ) &&
		( elTD.className == 'na' || elTD.className == 'period hover' || elTD.className == 'day' + getLength( this.arrChosenDays ) - 1 )
	) return;
	
	var day = el.innerHTML;
	var month = elTD.parentNode.getAttribute( 'month' ) - 1;
	var year = elTD.parentNode.getAttribute( 'year' );
	if( !day || !( month >= 0 ) || !year) return;
	
	var date = new Date(year, month, day);
	if ( !date.valueOf() ) return;
	// если количество выбранных дат уже равно допустимому количеству дат, то обнуляем все и ставим новую дату на первый перелет
	if( getLength( this.arrChosenDays ) == this.avToSelect ) {		// 1 если туда, 2 - туда и обратно
		this.notify( 'CalendarDayUnSelected', getLength( this.arrChosenDays ) - 1 );
		this.clear();
	}
	var index = 0;
	for ( var ii = 0; ii <= this.avToSelect - 1; ii++ ){
		if ( this.arrChosenDays[ ii ] == undefined ){
			index = ii;
			break;
		}
		//var index = getLength( this.arrChosenDays );
	}
	this.setDateToArray( date, index, elTD );
	this.notify( 'CalendarDaySelected', { 'date': date, 'index': index });
}

// -------------------------------------------------------------------------- //
// заносим дату в массив дат для возможности расскрашивания
Calendar.prototype.setDateToArray = function( cDate, index, el ) {	
	this.arrChosenDays[ index ] = {};
	this.arrChosenDays[ index ].date = cDate;
	this.arrChosenDays[ index ].el = el;
	this.arrChosenDays[ index ].idx = el.getAttribute('idx');
	el.className = 'day' + index;
	
	this.setStatus();	//внешний вид всего блока
	this.setNAdates();	//до выбранной даты присваиваем класс na
	this.setPeriod();	//раскрашиваем период
	//this.check();
}

// присваиваем класс родителю всех дат
Calendar.prototype.setStatus = function(){
	if (this.avToSelect == 1) {
		this.elementDays.className = 'day0';
	}
	else if ( getLength( this.arrChosenDays ) < this.avToSelect) {
		if ( getLength( this.arrChosenDays ) > 0 && this.arrChosenDays[ 0 ] == undefined ){
			this.elementDays.className = 'day0';
		}
		else{
			this.elementDays.className = 'day' + getLength( this.arrChosenDays );
		}
	}
	else {
		this.elementDays.className = 'na';
	}
}

// присваиваем класс датам, которые запрещаются для выбора
Calendar.prototype.setNAdates = function( ToIdx, FromIdx ){	
	if ( this.avToSelect > 1 && getLength( this.arrChosenDays ) > 0 ){
		FromIdx = FromIdx || 0;
		if ( getLength( this.arrChosenDays ) > 0 && this.arrChosenDays[ 0 ] == undefined ){
			FromIdx = this.arrChosenDays[ getLastNumberOfDate( this.arrChosenDays ) ].idx;
			ToIdx = ToIdx || this.arrAllDays.length - 1;
		}
		else {
			ToIdx = ToIdx || this.arrChosenDays[ getLength( this.arrChosenDays ) - 1 ].idx - 0;
		}
		var pattern = /day\d{1}/;
		for (var j = FromIdx; j < ToIdx; j++) {
			if ( !pattern.test( this.arrAllDays[ j ].className ) ){
				this.arrAllDays[ j ].className = 'na';
			}
		}
		//return true;
	}
	/*else {
		return false;
	}*/
}

// расскрашиваем период
Calendar.prototype.setPeriod = function( ToIdx, FromIdx ) {
	// попытка исправить ошибку при вводе второй даты без первой
	//if (this.arrChosenDays.length && this.arrChosenDays.length > 1 && this.arrChosenDays[ 0 ] == undefined ){}
	//else {
		this.arrAllDays.removeClass( 'period' );
		if ( getLength( this.arrChosenDays ) == this.avToSelect ) {
			FromIdx = FromIdx || this.arrChosenDays[ 0 ].idx - 0;
			ToIdx = ToIdx || this.arrChosenDays[ getLength( this.arrChosenDays ) - 1 ].idx - 0;
			var pattern = /day\d{1}/;
			for (var j = FromIdx + 1; j < ToIdx; j++) {
				if ( !pattern.test( this.arrAllDays[ j ].className ) ) {
					this.arrAllDays[ j ].className = 'period';
				}
			}
		}
	//}
	/*else {
		return false;
	}*/
}

// -------------------------------------------------------------------------- //
// обнулить даты. Если нет параметра, то все. Если есть, то это количество с конца списка
Calendar.prototype.clear = function( iToClearCol ) {
	var list = this.arrChosenDays;
	var iTCC = ( iToClearCol > getLength( list ) ? false : iToClearCol ) || getLength( list );

	for( var i = 0; i < iTCC; i++ ) {
		//this.setFrame( false, list.length - 1 );
		this.clearDate( getLength( list ) - 1 );
		//this.arrChosenDays[ list.length - 1 ].el.className = '';
		delete this.arrChosenDays[ getLength( list ) - 1 ];
	}
	//this.arrAllDays.removeClass( 'na' );
	//this.arrAllDays.removeClass( 'period' );
	this.arrAllDays.attr({ 'class': '' });
	this.elementDays.className = 'day0';
	//this.check();
	//this.createPeriod();
}

// очистка одной даты. Когда в форме изменяется дата, т.е. она есть в массиве выбранных дат, то ее надо очистить
Calendar.prototype.clearDate = function( index ) {
	this.arrChosenDays[ index ].el.className = '';
}


// ---------------------- Calendar setDate from inputs ---------------------- //
Calendar.prototype.setDate = function( obj ){
	if ( !obj[ 'data' ] ) return;
	//var type = obj[ 'type' ];
	var index = obj[ 'index' ];	// Number( type.substr( 1 ) );
	var date = obj[ 'data' ];
	var year = date.getFullYear();
	var month = date.getMonth() + 1;
	var day = date.getDate();
	
	var arrEls = $('#days tr[year=' + year + '][month=' + month + '] td:contains(' + day + ') div');
	var el;
	for ( var i = 0; i < arrEls.length; i++ ){
		if ( arrEls[ i ].innerHTML == day ){
			el = arrEls[ i ];
			break;
		}
	}
	
	var topEl = $( el ).parents( 'tr' ).prevAll( 'tr.newMonth' )[ 0 ];	//.offsetTop;
	if ( topEl == undefined ) topEl = $( el ).parents( 'tr' )[ 0 ];
	var top = topEl.offsetTop;
	//var top = el.parentNode.parentNode.offsetTop;
	var newTopPos = ( -1 * top ) + 'px';
	if (controller && controller.Id != 'RailwayController') {
		$('#calendar-wrap #days').animate({'top': newTopPos}, 500, 'linear');
	}
	
	if ( this.arrChosenDays[ index ] ){
		this.clearDate( index );
	}
	this.setDateToArray( date, index, el.parentNode );
}


// -------------------------------------------------------------------------- //
// скролл календаря
Calendar.prototype.scroll = function( params, ev ) {
	ev = ev || window.event;
	//alert( ev.detail * ( -1 ) );
	//var wheelData = -ev.detail;
	var evDetail = ( Number( ev.detail ) == NaN ) ? false : ev.detail;
	var evWheelData = ( ev.wheelData === undefined ) ? false : ev.wheelData;
	var wheelData = ( evDetail ) ? -ev.detail : ( ev.wheelDelta / 40 );
	//alert( 'scroll' );

	var elDays = $('#calendar-wrap #days');
	var strTop = elDays.css( 'top' );
	strTop = strTop.substr( 0, strTop.length - 2);
	var curTopPos = parseInt( strTop ) * ( -1 );
	var blockHeight = $('#days-wrap').height();
	
	var newTopPos = curTopPos - wheelData * 60;
	if ( newTopPos < 0 ) newTopPos = 0;
	if ( newTopPos > elDays.height() - blockHeight ) newTopPos = elDays.height() - blockHeight;
	newTopPos = String(newTopPos * ( -1 )) + 'px';
	elDays.css( 'top', newTopPos );
	
	//this.stopPropagation( ev );
	this.preventDefault( ev );
}
