var Calendar = Class.create();
Calendar.prototype = {
    initialize: function(div, props)
    {
        try
        {
            this.id = $(div).id;
            this.calenderTable = this.drawTable();
            $(div).appendChild(this.calenderTable);
            this.props = props;
        }
        catch(e)
        {
        }
    },
    
    drawTable: function(date)
    {
        this.date = (date == null) ? new Date() : date;
        try
        {
            var year = this.date.getFullYear();
            var month = this.date.getMonth() + 1;
            var calendarTable = document.createElement('table');
            calendarTable.id = this.id + 'Table';
            
            this.calendarTableHeader = this.drawHeader();
            calendarTable.appendChild(this.calendarTableHeader);
            this.calendarTableBody = this.drawMonth(year, month);
            calendarTable.appendChild(this.calendarTableBody);
            return calendarTable;
        }
        catch(e)
        {
        }
    },
    
    drawHeader: function()
    {
        var dayAbbreviations = new Array('0', 'M', 'T', 'W', 'T', 'F', 'S', 'S');
        var thead, tr, td, th, docFragment, textNode;
        thead = document.createElement('thead');
        thead.id = this.id + 'TableHead';
            docFragment = document.createDocumentFragment();
                tr = document.createElement('tr');
                    td = document.createElement('td');
                    td.setAttribute('colSpan', '7');
                    td.setAttribute('align', 'center');
                        var indicatorTable = this.drawIndicatorTable();
                    td.appendChild(indicatorTable);
                tr.appendChild(td);
            docFragment.appendChild(tr);
                tr = document.createElement('tr');
                for (var i = 1; i < dayAbbreviations.length; i++)
                {
                    th = document.createElement('th');
                        textNode = document.createTextNode(dayAbbreviations[i]);
                    th.appendChild(textNode);
                    tr.appendChild(th);
                }
            docFragment.appendChild(tr);
        thead.appendChild(docFragment);
        return thead;
    },
    
    drawMonth: function(year, month)
    {
        var dayCount = this.getDayCount(year, month);
        var tbody, docFragment, tr, td, textNode;
        tbody = document.createElement('tbody');
        tbody.id = this.id + 'TableBody';
            docFragment = document.createDocumentFragment();
            for (var i = 1; i <= 6; i++)
            {
                var row = this.drawWeek(year, month, dayCount, i);
                docFragment.appendChild(row);
            }
        tbody.appendChild(docFragment);
        return tbody;
    },
    
    drawWeek: function(year, month, dayCount, weekNumber)
    {
        var today = new Date();
        var dayName = Date.parseString(year + '-' + month + '-1', 'yyyy-M-d').getDay();
        dayName = (dayName == 0) ? 7 : dayName;
        var dayShift = dayName - 1;
        var lastDay = 7 * weekNumber - dayShift;
        var firstDay = lastDay - 6;
        var tr, td, textNode, divText;
        tr = document.createElement('tr');
        for (var i = firstDay; i <= lastDay; i++)
        {
            var cellText = (i > 0 && i <= dayCount) ? i : '&nbsp;';
            td = document.createElement('td');
            /*if (today.getFullYear() == year && today.getMonth == (month + 1) && today.getDate() == i)
                td.className = "CalendarToday";*/
                //textNode = document.createTextNode(cellText);
                divText = document.createElement('div');
                divText.innerHTML = cellText;
            //td.appendChild(textNode);
            td.appendChild(divText);
            if (cellText != '&nbsp;')
                td.onclick = this.selectDayEvent.bindAsEventListener(this);
            tr.appendChild(td);
        }
        return tr;
    },
    
    getDayCount: function(year, month)
    {
        var dayCount = 0;
        switch(month)
        {
            case 2:
                dayCount = (Date.isValid(year + '.' + month + '.29','yyyy.M.d')) ? 29 : 28;
                break;
            default:
                dayCount = (Date.isValid(year + '.' + month + '.31','yyyy.M.d')) ? 31 : 30;
                break;
        }
        return dayCount;
    },
    
    drawMonthIndicator: function()
    {
        var month = this.date.getMonth() + 1;
        var input;
        input = document.createElement('input');
        input.id = this.id + 'MonthIndicator';
        input.setAttribute('readOnly', 'true');
        input.setAttribute('size', '10');
        input.setAttribute('textAlign', 'right');
        input.value = this.date.getMonthName();
        input.onkeydown = this.changeMonthEvent.bindAsEventListener(this);
        input.onfocus = function() {input.select();}
        input.onchange = function() {input.select();}
        input.onclick = function() {input.focus(); input.select();}
        return input;
    },
    
    drawYearIndicator: function()
    {
        var year = this.date.getFullYear();
        var input;
        input = document.createElement('input');
        input.id = this.id + 'YearIndicator';
        input.setAttribute('readOnly', 'true');
        input.setAttribute('size', '4');
        input.value = year;
        input.onkeydown = this.changeYearEvent.bindAsEventListener(this);
        input.onfocus = function() {input.select();}
        input.onchange = function() {input.select();}
        return input;
    },
    
    drawIndicatorTable: function()
    {
        try
        {
            var table, tbody, tr, td;
            table = document.createElement('table');
            table.setAttribute('cellSpacing', '0');
            table.setAttribute('cellPadding', '0');
                tbody = document.createElement('tbody');
                    tr = document.createElement('tr');
                        td = document.createElement('td');
                        td.setAttribute('align', 'center');
                            var prevMonth = document.createElement('div');
                            prevMonth.innerHTML = '<a href="javascript:void(0)">&lt</a>';
                            prevMonth.onclick = this.gotoPreviousMonth.bindAsEventListener(this);
                        td.appendChild(prevMonth);
                    tr.appendChild(td);
                        td = document.createElement('td');
                        td.setAttribute('align', 'center');
                            var monthIndicator = this.drawMonthIndicator();
                        td.appendChild(monthIndicator);
                    tr.appendChild(td);
                        td = document.createElement('td');
                        td.setAttribute('align', 'center');
                            var yearIndicator = this.drawYearIndicator();
                        td.appendChild(yearIndicator);
                    tr.appendChild(td);
                        td = document.createElement('td');
                        td.setAttribute('align', 'center');
                            var nextMonth = document.createElement('div');
                            nextMonth.innerHTML = '<a href="javascript:void(0)">&gt</a>';
                            nextMonth.onclick = this.gotoNextMonth.bindAsEventListener(this);
                        td.appendChild(nextMonth);
                    tr.appendChild(td);
                tbody.appendChild(tr);
            table.appendChild(tbody);
            return table;
        }
        catch(e)
        {
        }
    },
    
    changeMonthEvent: function(evt)
    {
        try
        {
            var month = this.date.getMonth();
            var nextMonth = (month == 11) ? 0 : month + 1;
            var prevMonth = (month == 0) ? 11 : month - 1;
            var keyCode;
            if (evt.keyCode)
                keyCode = evt.keyCode;
            else if (e.which)
                keyCode = window.event.which;
            var validKey = true;
            var monthToGo;
            switch (keyCode)
            {
                case 39:
                    $(this.id + 'YearIndicator').focus();
                    validKey = false;
                    break;
                case 38:
                    monthToGo = prevMonth;
                    break;
                case 40:
                    monthToGo = nextMonth;
                    break;
                default:
                    validKey = false;
                    break;
            }
            if(validKey == true)
            {
                var input = Event.findElement(evt, 'input');
                this.date = new Date(this.date.getFullYear(), monthToGo, this.date.getDate());
                input.value = (new Date(2000, monthToGo, 1)).getMonthName();
                $(this.id + 'Table').replaceChild(this.drawMonth(this.date.getFullYear(), this.date.getMonth() + 1), $(this.id + 'Table').tBodies[0]);
                input.select();
            }
            return true;
        }
        catch(e)
        {
            return false;
        }
    },
    
    gotoNextMonth: function()
    {
        var date = this.date.add('M', 1);
        this.gotoDate(date);
    },
    
    gotoPreviousMonth: function()
    {
        var date = this.date.add('M', -1);
        this.gotoDate(date);
    },
    
    gotoDate: function(date)
    {
        this.date = date;
        var monthIndicator = $(this.id + 'MonthIndicator');
        var yearIndicator = $(this.id + 'YearIndicator');
        monthIndicator.value = this.date.getMonthName();
        yearIndicator.value = this.date.getFullYear();
        $(this.id + 'Table').replaceChild(this.drawMonth(this.date.getFullYear(), this.date.getMonth() + 1), $(this.id + 'Table').tBodies[0]);
    },
    
    changeYearEvent: function(evt)
    {
        try
        {
            var input = Event.findElement(evt, 'input');
            var year = this.date.getFullYear();
            var nextYear = (year == 2050) ? 2050 : year + 1;
            var prevYear = (year == 1900) ? 1900 : year - 1;
            var keyCode;
            if (evt.keyCode)
                keyCode = evt.keyCode;
            else if (e.which)
                keyCode = window.event.which;
            var validKey = true;
            var yearToGo;
            switch (keyCode)
            {
                case 37:
                    $(this.id + 'MonthIndicator').focus();
                    validKey = false;
                    break;
                case 38:
                    yearToGo = prevYear;
                    break;
                case 40:
                    yearToGo = nextYear;
                    break;
                default:
                    validKey = false;
                    break;
            }
            if(validKey == true)
            {
                this.date = new Date(yearToGo, this.date.getMonth(), this.date.getDate());
                input.value = yearToGo;
                $(this.id + 'Table').replaceChild(this.drawMonth(this.date.getFullYear(), this.date.getMonth() + 1), $(this.id + 'Table').tBodies[0]);
                input.select();
            }
        }
        catch(e)
        {
        }
    },
    
    selectDayEvent: function(evt)
    {
        try
        {
            if (this.props.onSelect)
            {
                var cell = Event.findElement(evt, 'div');
                //var divText = cell.childNodes[0];
                var year = this.date.getFullYear();
                var month = (this.date.getMonth() + 1);
                month = (month < 10) ? '0' + month : month;
                var day = cell.innerHTML;
                day = (day < 10) ? '0' + day : day;
                var date = year + '.' + month + '.' + day;
                this.props.onSelect(date);
            }
        }
        catch(e)
        {
        }
    }
}
