function showCalendar(target, caller, e)
{
	var day = $GbID(target + 'Day').value;
	var month = $GbID(target + 'MonthYear').value.substr(5, 2)*1 - 1;
	var year = $GbID(target + 'MonthYear').value.substr(0, 4);
	
	calendar.setDate(new Date(year, month, day));
	var holder = $GbID('calendarPopup');
	
	var position = getBounds(caller);

	holder.style.top = position.top + 25 + "px";
	holder.style.left = position.left + 1 + "px";
	
	if (navigator.userAgent.indexOf("MSIE") > -1)
	{
		holder.style.top = position.top + 26 + "px";
		holder.style.left = position.left + 2 + "px";
	}
	if (navigator.userAgent.indexOf("Opera") > -1)
	{
		holder.style.top = position.top + 24 + "px";
		holder.style.left = position.left + "px";
	}
	
	calendar.setTarget(target);
	calendar.process(true);
	e = e || window.event;
	addHandler(document.getElementsByTagName('html')[0], "click", checkCalendar);
	stopEventBubble(e);
}

function setSecondMonth(event)
{
	var sender = event.target || event.srcElement;
	$GbID('searchFly_arrivalMonthYear').value = sender.value;
}

function checkCalendar(e)
{
	e = e || window.event;
	var c = $GbID('calendarPopup');
	var parent = e.target || e.srcElement;
	while(parent)
	{
		if (parent == c) return;
		parent = parent.parentNode;
	}
	hide(c);
	removeHandler(document.getElementsByTagName('html')[0], "click", checkCalendar);
}

var MONTH_NAMES = new Array();
MONTH_NAMES["ru"] = ["январь","февраль","март","апрель","май","июнь","июль","август","сентябрь","октябрь","ноябрь","декабрь"];
MONTH_NAMES["en"] = ["january","february","march","april","may","june","july","august","september","october","november","december"];

function Calendar()
{
	var now = new Date();
	
    this.mainNode = null;
    this.root = null;    
    this.buffer = null;
    
    this.header = null;    
    this.body = null;
    
    this.date = new Date();   
    this.days = new Array(); 
    this.daysInMonth = 0;
    
    this.blankDaysRow = null;
    this.wasShown = false;
	
	this.fromYear = now.getFullYear();
	this.toYear = now.getFullYear()+1;
    this.fromMonth = now.getMonth();
    this.toMonth = now.getMonth();
    this.fromDay = 0;
    this.toDay = 31;
	
    this.getResultFunction = null;
	this.target = null;
	
	this.monthSelector = null;
	this.yearSelector = null;
	
	this.selects = null;
    this.lang = "RU";

    this.initialized = false;
}

Calendar.prototype.setTarget = function(elem)
{
    var target = null;
	if (typeof elem == "string") 
	{
		this.target = elem;
	}
	else 
	{
		try 
		{
			target = eval(elem)
		} 
		catch (e) 
		{
			target = null;
		}
		this.target = target;
	}
}

Calendar.prototype.getTarget = function()
{
	return this.target;
}

Calendar.prototype.getDate = function()
{
	return new Date(this.date);
}

Calendar.prototype.setDate = function(date)
{
	this.date = date;
}

Calendar.prototype.getLang = function()
{
	return this.lang.toUpperCase();
}

Calendar.prototype.printResult = function(elem)
{
    var target = this.getTarget();
    var date = new Date(parseInt(elem.name));
	var dayNum = (date.getDate() < 10) ? '0' + date.getDate() : date.getDate();
	var month = date.getMonth() + 1;
	var monthNum = ( month < 10) ? '0' + month : month;
	$GbID(target + "Day").value = dayNum;
	/*$GbID(target + "MonthYear").value = monthNum + "." + date.getFullYear();*/
	$GbID(target + "MonthYear").value = date.getFullYear() + "-" + monthNum;
	
	if (target == "searchFly_departure")
	{
	    $GbID("searchFly_arrivalMonthYear").value = date.getFullYear() + "-" + monthNum;
	}
	$('#searchFly_departureMonthYear, #searchFly_departureDay').change();
	$('#searchFly_arrivalDay, #searchFly_arrivalMonthYear').change();
	hide(this.mainNode);
}

Calendar.prototype.setFromMonth = function(num)
{
	this.fromMonth = num;
}
Calendar.prototype.setToMonth = function(num)
{
	this.toMonth = num;
}
Calendar.prototype.setFromYear = function(num)
{
	this.fromYear = num;
}
Calendar.prototype.setToYear = function(num)
{
	this.toYear = num;
}
Calendar.prototype.setFromDay = function(num)
{
	this.fromDay = num;
}
Calendar.prototype.setToDay = function(num)
{
	this.toDay = num;
}

Calendar.prototype.nextMonth = function()
{
    var oldDate = new Date(this.date);
    var newDate = new Date(oldDate.setMonth(oldDate.getMonth() + 1, oldDate.getDate()));
    if(this.isValidDate(newDate, 'MONTH'))
    {
        this.date = newDate;
        this.process(true);
    }
}

Calendar.prototype.prevMonth = function()
{
    var oldDate = new Date(this.date);
    var newDate = new Date(oldDate.setMonth(oldDate.getMonth() - 1, oldDate.getDate()));
    if(this.isValidDate(newDate, 'MONTH'))
    {
        this.date = newDate;
        this.process(true);
    }
}

Calendar.prototype.setMonth = function(num)
{
    var newDate = new Date(this.date);
    newDate.setMonth(num, newDate.getDate());
    if(this.isValidDate(newDate, 'MONTH'))
    {
        this.date = new Date(newDate);
        this.process(true);
    }
    else
    {
        if(this.date.getFullYear() == this.fromYear)
        {
            newDate.setMonth(this.fromMonth, newDate.getDate());
        }
        else if(this.date.getFullYear() == this.toYear)
        {
            newDate.setMonth(this.toMonth, newDate.getDate());
        }
        this.date = new Date(newDate);
        this.process(true);
    }
}

Calendar.prototype.setYear = function(num)
{
    var newDate = new Date(this.date);
    newDate.setFullYear(num, newDate.getMonth(), newDate.getDate());
    if(this.isValidDate(newDate, 'YEAR'))
    {
        if(!this.isValidDate(newDate, 'MONTH'))
        {
            if(this.date.getFullYear() == this.fromYear)
            {
                newDate.setMonth(this.fromMonth, newDate.getDate());
            }
            else if(this.date.getFullYear() == this.toYear)
            {
                newDate.setMonth(this.toMonth, newDate.getDate());
            }
        }
        this.date = new Date(newDate);
        this.process(true);
    }
}

Calendar.prototype.isValidDate = function(date, mode)
{
    mode = (typeof(mode) == 'string') ? mode : "ALL";
    var from = 0;
    var to = 0;
    var curr = 0;
    if(mode.toUpperCase() == 'YEAR')
    {
        from = parseInt(this.fromYear);
        to = parseInt(this.toYear);
        curr = parseInt(date.getFullYear());
    }
    else if(mode.toUpperCase() == 'MONTH')
    {
        from = parseInt(this.fromYear + '' + ( (this.fromMonth < 10) ? '0'+this.fromMonth : this.fromMonth ));
        to = parseInt(this.toYear + '' + ( (this.toMonth < 10) ? '0'+this.toMonth : this.toMonth ));
        curr = parseInt(date.getFullYear() + '' + ( (date.getMonth() < 10) ? '0'+date.getMonth() : date.getMonth() ));
    }
    else
    {
        from = parseInt(this.fromYear + '' + ( (this.fromMonth < 10) ? '0'+this.fromMonth : this.fromMonth ) + '' + ( (this.fromDay < 10) ? '0'+this.fromDay : this.fromDay ));
        to = parseInt(this.toYear + '' + ( (this.toMonth < 10) ? '0'+this.toMonth : this.toMonth ) + '' + ( (this.toDay < 10) ? '0'+this.toDay : this.toDay ) );
        curr = parseInt(date.getFullYear() + '' + ( (date.getMonth() < 10) ? '0'+date.getMonth() : date.getMonth() ) + '' + ( (date.getDate() < 10) ? '0'+date.getDate() : date.getDate() ));
    }
    return (curr >= from && curr <= to);
}

Calendar.prototype.init = function (prefix)
{
    this.mainNode = $GbID(prefix);
    this.root = this.mainNode.getElementsByTagName('TABLE')[0];
    this.header = this.root.tHead;
    this.body = this.root.tBodies[this.root.tBodies.length - 1];

    if(!this.initialized)
    {
        this.initGlobalVariables();
    }
}

Calendar.prototype.show = function()
{
    if(!this.mainNode)
    {
        return false;
    }

    if(this.mainNode.offsetHeight > 0)
	{
		this.process(false);
	}	
	else
	{
		this.process(true);
	}
}

Calendar.prototype.process = function(isShow)
{
    if(this.buffer == null)
    {
        this.buffer = this.root.cloneNode(true);
        hide(this.buffer);
    }

    if(this.wasShown) // if was shown, then we need to clear old values
    {
        var count = this.root.tHead.rows.length;
        for(var i=0; i<count; i++)
        {
            this.root.tHead.deleteRow(i);
        }
        for(var i=0; i<this.root.tBodies.length; i++)
        {
            count = this.root.tBodies[i].rows.length;
            for(var j=count-1; j>=0; j--)
            {
                this.root.tBodies[i].deleteRow(j);
            }
        }

        // then insert default templates
        for(var i=0; i<this.buffer.tHead.rows.length; i++)
        {
            this.header.appendChild(this.buffer.tHead.rows[i].cloneNode(true));
        }
        for(var i=0; i<this.buffer.tBodies.length; i++)
        {
            for(var j=0; j<this.buffer.tBodies[i].rows.length; j++)
            {
                this.root.tBodies[i].appendChild(this.buffer.tBodies[i].rows[j].cloneNode(true));
            }
        }

        this.wasShown = false;
    }

    if(!isShow)
    {
		hide(this.mainNode);
        return true;
    }

    this.parse(this.header);
    this.getDays();
    this.prepareDayRows();

	if(this.monthSelector) // Если месяц нужно выводить в селект-бокс
	{
		this.initMonthSelect(this.monthSelector.id)
	}
	if(this.yearSelector) // Если год нужно выводить в селект-бокс
	{
		this.setYearSelectedIndex();
	}

	$GbID("calendarCurMonthName").innerHTML = MONTH_NAMES[this.lang][this.getDate().getMonth()];
	$GbID("calendarCurYear").innerHTML = this.getDate().getFullYear();

    if(isShow)
    {
		show(this.mainNode);
        this.wasShown = true;
    }
}

Calendar.prototype.parse = function(node, value)
{
    if(node.nodeType == 3)   // if text node
    {
        var text = node.nodeValue;
        var endIndex = text.indexOf(']');
        var startIndex = text.indexOf('[');

        while(endIndex > startIndex)
        {
            var paramName = text.substring(startIndex+1, endIndex);
            if(value)
            {
                text = text.replace('[' + paramName + ']', value);
            }
            else
            {
                text = text.replace('[' + paramName + ']', this.getParamValue(paramName));
            }

            endIndex = text.indexOf(']');
            startIndex = text.indexOf('[');
        }

        node.nodeValue = text;
    }
    else if(node.nodeType == 1) // if HTML object node
    {
        var nodes = node.childNodes;
		if(node.tagName == 'INPUT')
		{
			node.value = node.value.replace('[NUM]', value);
		}
        for(var i=0; i<nodes.length; i++)
        {
           this.parse(nodes[i], value); // recursive parse child nodes  
        }
    }
}

Calendar.prototype.getDays = function()
{
    this.days = new Array();
    var tmpDate = new Date(this.date);

    tmpDate.setDate(1);

    var offsetLeft = tmpDate.getDay() - 1;
    if(tmpDate.getDay() == 0)
    {
        offsetLeft = 6;
    }

    this.daysInMonth = tmpDate.getDaysInMonth();
    var offsetRight = 7 - ( new Date( tmpDate.setDate(this.daysInMonth) ) ).getDay();
    offsetRight = ( offsetRight == 7 ) ? 0 : offsetRight;

    var j = 1;
    for(var i = offsetLeft * -1; i < (this.daysInMonth + offsetRight); i++ )
    {
        if(this.daysInMonth <= i)
        {
            this.days[this.days.length] = j;
            j++;
        }
        else
        {
            this.days[this.days.length] = (i >= 0) ? i+1 : i;
        }
    }
}

Calendar.prototype.getParamValue = function(name)
{
    var result = '';

    switch(name)
    {
        case 'MONTH_NAME':
            result = MONTH_NAMES[this.lang][this.date.getMonth()];
            break;
        case 'FULL_YEAR':
            result = this.date.getFullYear();
            break;
		case 'DAY':
			result = this.date.getDate();
			break;
    }

    return result;
}

Calendar.prototype.prepareDayRows = function()
{
    var rows = this.days.length / 7 - 1;

    for(var i=0; i<rows; i++)
    {
        this.body.appendChild( this.body.rows[0].cloneNode(true) );
    }

    var k = 0;
    var daysInPrevMonth = 0;
    for(var i=0; i<this.body.rows.length; i++)
    {
        tr = this.body.rows[i];
        for(var j=0; j<tr.cells.length; j++)
        {
            var day = new Date(this.date);

            var td = tr.cells[j];

            if(this.days[k] < 1) // if prev month
            {
                var month = this.date.getMonth() - 1;
                if( month < 0 )
                {
                    day.setFullYear(this.date.getFullYear() - 1, 11, day.getDate());
                }
				else
				{
					day.setMonth(month, 1);
				}
                var prevMonthDays = day.getDaysInMonth();
				var dayNum = prevMonthDays + this.days[k] + 1;
				day.setMonth(day.getMonth(), dayNum);
                td.className += ' anotherMonthDay';
                daysInPrevMonth++;
            }
            else if(k >= this.daysInMonth + daysInPrevMonth) // if next month
            {
                td.className += ' anotherMonthDay';
                day.setMonth(this.date.getMonth() + 1, this.days[k]);
            }
            else
            {
                day.setDate(this.days[k]);
                if(day.getDay() == 0 || day.getDay() == 6)
                {
                    td.className += ' holiday';
                }

                var now = new Date();
                if( day.getFullYear()+''+day.getMonth()+''+day.getDate() == now.getFullYear()+''+now.getMonth()+''+now.getDate() )
                {
                    td.className += ' today';
                }
            }

            var isValid = this.isValidDate(day);

            if(!isValid)
            {
                td.className += ' notValid';
            }

            this.parse(td, day.getDate());
            this.setDayClickHandler(td, day.getTime(), isValid);

            k++;
        }
    }
}

Calendar.prototype.setDayClickHandler = function(td, value, valid)
{
    var links = td.getElementsByTagName('INPUT');
    if(links.length == 0)
    {
        links = td.getElementsByTagName('A');
    }
    for(var i=0; i<links.length; i++)
    {
        if(valid)
        {
            links[i].name = value;
        }
        else
        {
            links[i].onclick = function() {return false;}
        }
    }
}

Calendar.prototype.initMonthSelect = function(id)
{
	this.monthSelector = getSelectById(id);

    if(!this.monthSelector)
	{
		alert('Ошибка инициализации!\nНе могу найти SELECT c ID="' + id + '"');
		return false;
	}

	this.monthSelector.options.length = 0;
	var index = 0;
    var selected = 0;
    for(var i = 1; i <= 12; i++)
	{
		if( this.toYear == this.date.getFullYear() && this.toMonth < i - 1 )
		{
			break;
		}
		else if( this.fromYear == this.date.getFullYear() && this.fromMonth > i - 1 )
		{
			continue;
		}
        if(i - 1 == this.date.getMonth())
        {
            selected = index;
        }
        appendOption(this.monthSelector, i - 1, MONTH_NAMES[this.lang][i-1], index );
		index++;
	}

	if (navigator.userAgent.indexOf('Opera') > -1) setTimeout(function(){this.monthSelector.selectedIndex = selected;}.bind(this), 0);
	else this.monthSelector.selectedIndex = selected;
}

Calendar.prototype.initYearSelect = function(id)
{
	this.yearSelector = getSelectById(id);

    if(!this.yearSelector)
	{
		alert('Ошибка инициализации!\nНе могу найти SELECT, c ID="' + id + '"');
		return false;
	}
	var index = 0;
	for(var i = this.fromYear; i <= this.toYear; i++ )
	{
		appendOption(this.yearSelector, i, i, index );
		index++;
	}
	if (navigator.userAgent.indexOf('Opera') > -1) setTimeout(function(){this.yearSelector.selectedIndex = this.date.getFullYear() - this.fromYear - 1;}.bind(this), 0);
	else this.yearSelector.selectedIndex = this.date.getFullYear() - this.fromYear - 1;
}

Calendar.prototype.setYearSelectedIndex = function()
{
	var index = this.date.getFullYear() - this.fromYear;
	if (navigator.userAgent.indexOf('Opera') > -1) setTimeout(function(){getSelectById(this.yearSelector.id).selectedIndex = index;}.bind(this), 0);
	else getSelectById(this.yearSelector.id).selectedIndex = index;
}

Calendar.prototype.initGlobalVariables = function()
{
    var lang = getAttributeByName(this.mainNode, 'LANG');
    if(lang != '')
    {
        this.lang = lang.toUpperCase();
    }

    var fromDate = getAttributeByName(this.mainNode, 'FROM_DATE');
    if(fromDate != '')
    {
        var fromDateVals = fromDate.split('.');
        if(fromDateVals.length == 0)
        {
            this.setFromYear(parseInt(fromDate));
        }
        else if(fromDateVals.length == 2)
        {
            this.setFromMonth(parseInt(fromDateVals[0]) - 1);
            this.setFromYear(parseInt(fromDateVals[1]));
        }
        else if(fromDateVals.length == 3)
        {
            this.setFromDay(parseInt(fromDateVals[0]));
            this.setFromMonth(parseInt(fromDateVals[1]) - 1);
            this.setFromYear(parseInt(fromDateVals[2]));
        }
    }

    var toDate = getAttributeByName(this.mainNode, 'TO_DATE');
    if(toDate != '')
    {
        var toDateVals = toDate.split('.');
        if(toDateVals.length == 0)
        {
            this.setToYear(parseInt(toDate));
        }
        else if(toDateVals.length == 2)
        {
            this.setToMonth(parseInt(toDateVals[0]) - 1);
            this.setToYear(parseInt(toDateVals[1]));
        }
        else if(toDateVals.length == 3)
        {
            this.setToDay(parseInt(toDateVals[0]));
            this.setToMonth(parseInt(toDateVals[1]) - 1);
            this.setToYear(parseInt(toDateVals[2]));
        }
    }

    var target = getAttributeByName(this.mainNode, 'TARGET');
    if(target != '')
    {
        this.setTarget(target);
    }

    var startDate = getAttributeByName(this.mainNode, 'START_DATE');
    if(startDate != '')
    {
        var startDateVals = startDate.split('.');
        var startTime = new Date();

        if(startDateVals.length == 0)
        {
            startTime.setFullYear(parseInt(startDate));
        }
        else if(toDateVals.length == 2)
        {
            startTime.setFullYear(parseInt(startDateVals[1]), parseInt(startDateVals[0]) - 1);
        }
        else if(toDateVals.length == 3)
        {
            startTime.setFullYear(parseInt(startDateVals[2]), parseInt(startDateVals[1]) - 1, parseInt(startDateVals[0]));
        }

        if(this.isValidDate(startTime))
        {
            this.setDate(new Date(startTime));
        }
    }

    this.initialized = true;
}

function getSelectById(id)
{
	if(this.root)
	{
		if(!this.selects)
		{
			this.selects = this.root.getElementsByTagName('SELECT');
		}
		for(var i = 0; i < this.selects.length; i++)
		{
			if(this.selects[i].id == id)
			{
				return this.selects[i];
			}
		}
		return null;
	}
	else
	{
		return $GbID(id);
	}
}

Date.IsLeapYear = function(year)
{
	if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))
	{
		return true;
	}
	return false;
}

Date.prototype.getDaysInMonth = function()
{
	var days = [31, '', 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
	
	var m = this.getMonth();
	var y = this.getFullYear();
	
	if (m != 1)
	{
		return days[m];
	}
	else
	{
		if (Date.IsLeapYear(y))
		{
			return 29;
		}
		else
		{
			return 28;
		}
	}
}

function appendOption(elem, value, text, index)
{
    elem.options[index] = new Option(text, value);
}

function getAttributeByName(elem, name)
{
	name = name.toUpperCase();
	try
	{
		var value = elem.getAttribute(name);
		return ( (value) ? value : '' );
	}
	catch(e)
	{
		return '';
	}
	return '';
}
