﻿/**
 * JS Calendar
 *
 * Usage:
 * ------
 * var calendar = new Calendar(day, month, year); -- constructor
 *
 * calendar.bindContainer(containerObj);
 * calendar.bindMonthBar(monthBarObj);
 * calendar.bindYearBar(yearBarObj);
 * calendar.bindMonthForward(monthForwardControl);
 * calendar.bindMonthBack(monthBackControl);
 * calendar.bindYearForward(yearForwardControl);
 * calendar.bindYearBack(yearBackControl);  --
 *                 all parameters are DOM object, get it by document.getElementById(id)
 *             containerObj - DIV element which is container for the calendar
 *             monthBarObj, yearBarObj - DIV element where current month and year are displayed
 *             monthForwardControl - any element (DIV, SPAN, IMG) which is "NEXT MONTH BUTTON"
 *             etc.
 *
 * calendar.bindHandler(onclickHandler); --
 *             onclickHandler(day, month, year) is called, when element is clicked,
 *             you should define it by yourself
 *
 * calendar.bindChecker(dayIsActiveChecker); --
 *             dayIsActiveChecker(day, month, year) is called to check, if the day is "active",
 *             that is if there is any page for this day, if user clicks this day, this page would open;
 *             if the day is not "active", nothing happens after clicking
 */

function Calendar(d, m, y)
{
    var _container, _monthBar, _yearBar, _monthBackCtrl, _monthForwardCtrl, _yearBackCtrl, _yearForwardCtrl;
    var _onclickHandler, _dayIsActiveChecker;
    this.bindContainer = function (c) { _container = c; _container && (_container.clearChildren = function () { while (0 != this.childNodes.length) { this.removeChild(this.firstChild); } }); }
    this.bindMonthBar = function (b) { _monthBar = b; }
    this.bindYearBar = function (b) { _yearBar = b; }
    this.bindMonthForward = function (mf) { _monthForwardCtrl = mf;}
    this.bindMonthBack = function (mb) { _monthBackCtrl = mb;}
    this.bindYearForward = function (yf) { _yearForwardCtrl = yf; }
    this.bindYearBack = function (yb) { _yearBackCtrl = yb; }
    this.bindHandler = function (h) { _onclickHandler = h; }
    this.bindChecker = function (c) { _dayIsActiveChecker = c; }

    /* engine */
    var _todayDay, _todayMonth, _todayYear, _day, _month, _year;
    var _monthNames = [null, 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
    var _getMonthDayCount = function (m, y) {
        var md = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
        !!y || (y = _year);
        !!m || (m = _month);
        
        if (2 == m && (0 == y % 400 || 0 == y % 4 && 0 != y % 100)) {
            return 29;
        } else {
            return md[m - 1];
        }
    }
    this.init = function () {
        var date = new Date();
        _todayDay = _day = d || date.getDate();
        _todayMonth = _month = m || date.getMonth() + 1;
        _todayYear = _year = y || date.getFullYear();
        _monthBackCtrl && (_monthBackCtrl.onclick = _monthBack);
        _monthForwardCtrl && (_monthForwardCtrl.onclick = _monthForward);
        _yearBackCtrl && (_yearBackCtrl.onclick = _yearBack);
        _yearForwardCtrl && (_yearForwardCtrl.onclick = _yearForward);
        _refresh();
    }

    var _refresh = function () {
        if (null == _container) {
            return false;
        }

        _container.clearChildren();
        _container.appendChild(_getDomDays());

        _monthBar && (_monthBar.innerHTML = _monthNames[_month]);
        _yearBar && (_yearBar.innerHTML = _year);
    }
    
    var _getDomDays = function () {
   
        var calendarUl = document.createElement('ul');
		
        var date = new Date(_year, _month - 1, 1);
        var dayOfWeek = 0 == date.getDay() ? 7 : date.getDay();

        if (1 != date.getDay()) {
            var prevMonthDayCount = _getMonthDayCount(1 == _month ? 12 : _month - 1, 1 == _month ? _year - 1 : _year);

            for (var k = 1; k < dayOfWeek; ++k) {
                var li = document.createElement('li');
                if (k == 1){
					li.className = "color-01";
				} else if (k == 7){
					li.className = "last color-03";
				} else {
					li.className = "color-02";
				}
                li.appendChild(document.createTextNode('' + (prevMonthDayCount - dayOfWeek + k + 1)));
                calendarUl.appendChild(li);
            }
        }
		
        for (var day = 1; day <= _getMonthDayCount(_month, _year); ++day) {

            var li = document.createElement('li');
			if (dayOfWeek == 1){
				li.className = "color-03";
			} else if (dayOfWeek == 7){
				li.className = "last color-03";
			}
            //_defaultCurrentClass && (li.className = _defaultCurrentClass);
            //(7 == dayOfWeek || 6 == dayOfWeek) && _weekendClass && (li.className = _weekendClass + ' ' + li.className);
            //(_todayDay == day) && _currentDayClass && (li.className = _currentDayClass + ' ' + li.className);
            li.onclick = (function (d) { return function () { _onclickHandler && _onclickHandler(d, _month, _year); } })(day);
	        if ((_activeClass) && (_dayIsActiveChecker) && (_dayIsActiveChecker(day, _month, _year))) {
				var a = document.createElement('a');
				a.href = '#';
				a.appendChild(document.createTextNode(day));
				li.appendChild(a)
			} else {
				li.appendChild(document.createTextNode('' + day));
			}
            calendarUl.appendChild(li);

            dayOfWeek = 7 == dayOfWeek ? 1 : dayOfWeek + 1;
        }		
	
        if (1 != dayOfWeek) {
            for (var k = dayOfWeek, m = 1; k <= 7; ++k, ++m) {
                var li = document.createElement('li');
				if (k == 7){
					li.className = "last color-01";
				} else {
					li.className = "color-02";					
				}
                li.appendChild(document.createTextNode('' + m));
                calendarUl.appendChild(li);
            }
        }
	
        return calendarUl;
    }
    this.getM = function(){return _month;}
    this.getY = function(){return _year;}

    /* view */
    var _defaultCurrentClass, _defaultOtherClass, _currentDayClass, _weekendClass, _activeClass;
    this.setDefaultCurrentClass = function (c) { _defaultCurrentClass = c; }
    this.setDefaultOtherClass = function (c) { _defaultOtherClass = c; }
    this.setCurrentDayClass = function (c) { _currentDayClass = c; }
    this.setWeekendClass = function (c) { _weekendClass = c; }
    this.setActiveDayClass = function (c) { _activeClass = c; }

    /* controlling */
    var _monthBack = function () { if (1 == _month) { _month = 12; --_year; } else { --_month }; _refresh(); moveMonthOnCalendar();}
    var _monthForward = function () { if (12 == _month) { _month = 1; ++_year; } else { ++_month; }; _refresh(); moveMonthOnCalendar();}
    var _yearBack = function () { --_year; _refresh(); }
    var _yearForward = function () { ++_year; _refresh(); }
}
