(function( $ ){
  $.fn.eventCalendar = function( options ) {
      // Настройки плагина по-умолчанию
     var settings = {
          'days' : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
          'months' : ['January','February','March','April','May','June','Jule','August','September','October','November','December'],
          'firstday' : 0,
          'limit': 0,
          'showEvents': 1
        },
        parent = $(this);
    
    // Перезаписываем настройки по умолчанию, настройками плагина, полученным от пользователя
    if ( options ) {
        $.extend( settings, options);
    }
    
    // Внутренние переменные, которые используются в плагине
    var width = this.width(),
        ceilHeight  = Math.floor ( width /  7 ),
        events = new Array(0,1,2,3,4,5,6,7,8,9,10,11),
        currentDate = new Date();
    
    // Прячем содержимое
    $(this).hide();
            
    // Создаем массив событий, упорядоченный по месяцам
    for ( monthNum=0; monthNum<=11; monthNum++ )
    {
        var monthEvents = [];
        $(this).find('li')
                .filter( function(index){
                    var eventDate = new Date( $(this).attr('rel') ).getMonth();
                    if ( eventDate === monthNum )
                        return true;
                    else
                        return false;
                } )
                .each( function(){
                    monthEvents.push( $(this) );
                });
        events[monthNum] = monthEvents;
    }
    
    // Функция, которая проверяет, есть ли события для этого дня в выбранном месяце
    var isEventsForDay = function(dayNum,events)
    {
        for ( var key in events)
        {
            var event = events[key];
            if ( dayNum === new Date( $(event).attr('rel') ).getDate() )
                return true;
        }
        return false;
    }
    
    // Функция, которая строит таблицу текущего месяца с данными
    var getMonthHtml = function(monthNum, events)
    {
        var thead = '<table class="calendar"><thead>',
            tbody = '<tbody>'
            tend = '</tbody></table>',
            daysCount = 32 - new Date( currentDate.getFullYear(), monthNum, 32).getDate(),
            firstDay = new Date( currentDate.getFullYear(), monthNum, 1 ).getDay(),
            eventsList = '',
            html = '';
        
        // Узнаем текущий это месяц или нет
        if ( monthNum === currentDate.getMonth() )
            currentDay = currentDate.getDate();
        else
            currentDay = false;
            
        // Строим навигацию по календарю
        var navigation = '<div class="navigation">';
        if ( monthNum === 0 )
        {
            navigation += '<div class="month-name">' 
                + settings.months[monthNum] + '</div>'
                +'<div class="next-btn">&gt;&gt;</div>';
        }
        else if ( monthNum === 11 )
        {
            navigation += '<div class="prev-btn">&lt;&lt;</div>'
                    +'<div class="month-name">' 
                    + settings.months[monthNum] + '</div>';
        }
        else {
            navigation += '<div class="prev-btn">&lt;&lt;</div>'
                    +'<div class="month-name">' 
                    + settings.months[monthNum] + '</div>'
                    +'<div class="next-btn">&gt;&gt;</div>';
        }
        navigation +='</div>';
              
        // Строим шапку сайта
        if ( settings.firstday === 1 )
        {
            thead += '<tr><td>' + settings.days[1] + '</td>'
                + '<td>' + settings.days[2] + '</td>'
                + '<td>' + settings.days[3] + '</td>'
                + '<td>' + settings.days[4] + '</td>'
                + '<td>' + settings.days[5] + '</td>'
                + '<td>' + settings.days[6] + '</td>'
                + '<td>' + settings.days[0] + '</td></tr></thead>';
            if ( firstDay === 0 )
                firstDay = 6;
            else
                firstDay--;
        }
        else
        {
            thead += '<tr><td>' + settings.days[0] + '</td>'
                + '<td>' + settings.days[1] + '</td>'
                + '<td>' + settings.days[2] + '</td>'
                + '<td>' + settings.days[3] + '</td>'
                + '<td>' + settings.days[4] + '</td>'
                + '<td>' + settings.days[5] + '</td>'
                + '<td>' + settings.days[6] + '</td></tr></thead>';
        }
        
        // Строим тело календаря
        var rows = Math.ceil( (firstDay + daysCount)/7 ),
            currentDayCeil = 1;  
        for ( i=0; i<rows; i++  )
        {
            tbody += '<tr>';
            for ( ii=0; ii<7; ii++)
            {
				
                var blaclass = 'ceil-day';
                if ( i === 0 && firstDay != ii && firstDay>ii )
                    tbody += '<td class="clear-ceil"></td>';
                else if ( i === rows-1 && currentDayCeil === daysCount+1 )
                    tbody += '<td class="clear-ceil"></td>';
                else {
                    if ( currentDayCeil === currentDay )
                        blaclass += ' current-day';
                    if ( isEventsForDay(currentDayCeil, events )  )
                        blaclass += ' events';
                    tbody += '<td class="' + blaclass + '">' + currentDayCeil + '</td>';
                    currentDayCeil++;
                }
            }
            tbody += '</tr>';
        }
        
        // Выводим список событий после календаря
        if ( settings.showEvents === 1 && events.length > 0 )
        {
            eventsList += '<ul class="events-list">';
            for ( var key in events )
            {
                if ( settings.limit > 0 && key + 1 === settings.limit )
                    break;
                eventsList += '<li rel="' + $(events[key]).attr('rel') + '">' + $(events[key]).html() + '</li>';
            }
            eventsList += '</ul>';
        }
        
        html += navigation + thead + tbody + tend + eventsList;
        
        return html;
    }
  
    return this.each( function() {
        var currentMonth = currentDate.getMonth(),
            monthForPrevBtn = currentMonth - 1,
            monthForNextBtn = currentMonth + 1; 
        
        $(this).html( getMonthHtml( currentDate.getMonth(), events[currentDate.getMonth()] ) );
        
        
        // Делегируем обработчик событий по нажатию клавиши назад (предыдущий месяц)
        $(this).delegate("div.prev-btn", "click", function(){
            $(parent).slideUp( 1000, function(){
                $(parent).html( getMonthHtml(monthForPrevBtn,events[monthForPrevBtn]) );
                currentMonth = monthForPrevBtn;
                monthForPrevBtn = currentMonth - 1;
                monthForNextBtn = currentMonth + 1;
                $(parent).slideDown( 1000 ); 
            } );
        });
        
        // Делегируем обработчик событий по нажатию клавиши вперед (следующий месяц)
        $(this).delegate("div.next-btn", "click", function(){
            $(parent).slideUp( 1000, function(){
                $(parent).html( getMonthHtml(monthForNextBtn,events[monthForNextBtn]) );
                currentMonth = monthForNextBtn;
                monthForPrevBtn = currentMonth - 1;
                monthForNextBtn = currentMonth + 1;
                $(parent).slideDown( 1000 ); 
            } );
        });
        
        // Делегируем обработчик событий для дат с событиями
        $(this).delegate('td.events', 'click', function(){
            var day = $(this).html();
            
            var collection = $(parent).find('ul.events-list li')
                    .filter( function(index){
                        var eventDate = new Date( $(this).attr('rel') ).getDate();
                        if ( eventDate == day )
                            return false;
                        else
                            return true;
                    });
            var count = collection.length;
            
            collection.fadeOut('slow', function(){
                count--;
                if ( !count )
                {
                    $(parent).find('ul.events-list li')
                        .filter( function(index){
                            var eventDate = new Date( $(this).attr('rel') ).getDate();
                            if ( eventDate == day )
                                return true;
                            else
                                return false;
                            })
                            .each( function(){
                                $(this).fadeIn('slow');
                            });
                }
            });            
        });
        
        // Делегируем обработчик событий для заголовка месяца
        $(this).delegate('div.navigation','click', function(){
            var collection = $(parent).find('ul.events-list li');
            var count = collection.length;
            collection.fadeOut('slow', function(){
                count--;
                if (!count)
                {
                   $(parent).find('ul.events-list li').each( function(){
                      $(this).fadeIn('slow'); 
                   });
               };
            });
        });
        
        $(this).fadeIn(1000);
    });

  };
})( jQuery );

