/**
 * jQuery calendarLite plugin
 *
 * Copyright (c) 2009 Snitko Roman
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * @author 	Roman Snitko snowcore.net@gmail.com
 * @link http://snowcore.net/
 * @version 0.1.11
 */
;(function($){
    $.fn.calendarLite = function(options) {
        var opts = $.extend({}, $.fn.calendarLite.defaults, options);
        return this.each(function() {
            $this = $(this);
            var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
            $.fn.calendarLite.draw(o);
        });
    };
    
    /**
     * Get calendar's header (day names)
     * @param {Object} opts
     */
    $.fn.calendarLite.getHead = function(opts) {
        var html = [];
        for (var i = 0; i < opts.days.length; i++) {
            html.push('<th>' + opts.days[i] + '</th>');
        }
        return html.join('');
    };
    
    /**
     * Main function for drawing calendar
     * @param {Object} opts
     */
    $.fn.calendarLite.draw = function(opts) {
        var o = $.extend({}, this.defaults, opts);
        
        month = parseInt(o.month, 10);
        year = parseInt(o.year, 10);

        var today = new Date();
        var srcDate = new Date();
        if (!isNaN(year)) {
            srcDate.setDate(1);
            srcDate.setFullYear(year);
        }
        if (!isNaN(month)) {
            srcDate.setDate(1);
            srcDate.setMonth(month);
        }
        var curDate = srcDate.getDate();
        var curMonth = srcDate.getMonth();
        var curYear = srcDate.getFullYear();

        var dates = [];
        var dayCount = new Date(curYear, curMonth + 1, 0).getDate();
        for (var i = 1; i <= dayCount; i++) {
            var tmpDate = new Date(curYear, curMonth, i);
            if (tmpDate.getMonth() == curMonth && tmpDate.getFullYear() == curYear) {
                dates.push(tmpDate);
            }
        }

        var table = $('<table cellspacing="1" class="table-kalendar"></table>');
        var str = '<tbody><tr>' + this.getHead(o) + '</tr>', cl = '';
        var line = [];

        loadEvents(curYear, curMonth + 1, opts, function()
        {
            for (var j = 0; j < dates.length; j++) {
                var day = dates[j].getDay();
                var month = dates[j].getMonth();
                var year = dates[j].getFullYear();

                var date = dates[j].getDate();
                var rel = _formatLink(o.dateFormat, dates[j]);
                cl = '';
                if (date == today.getDate() && curMonth == today.getMonth() && curYear == today.getFullYear()) {
                    cl = ' class="curr"';
                } else if (day == 6 || day == 0) {
                    cl = ' class="weekend"';
                }
                var href = '#';
                if (o.linkFormat != null && o.linkFormat != undefined) {
                    href = _formatLink(o.linkFormat, dates[j]);
                }

                if(isEventAtDay(curYear, curMonth + 1, date, opts)){
                    line.push('<td' + cl + '><a href="' + href + '" rel="' + rel + '">' + date + '</a></td>');
                }
                else{
                    line.push('<td' + cl + '>' + date + '</td>');
                }

                if (dates[j].getDay() == 0) {
                    if (line.length < 7) {
                        var ln = line.length;
                        var pad = [];
                        for (var k = 0; k < (7 - ln); k++) {
                            pad.push('<td>&nbsp;</td>');
                        }
                        line = pad.concat(line);
                    }
                    str += '<tr>' + line.join('') + '</tr>';
                    line = [];
                } else if (j == (dates.length - 1)) {
                    str += '<tr>' + line.join('') + '</tr>';
                }
            }
            str += '</tbody>';
            table.html(str);
            if (typeof o.onSelect == 'function') {
                table.find('a').click(function(){
                    return o.onSelect($(this).attr('rel'));
                });
            }
            
            var y = '';
            if (o.showYear == true) {
                y = ' ' + curYear + ' ';
            }

            $this[0].innerHTML = '<span class="state" style="display:none;">' + curMonth + '.' + curYear + '</span><div class="monthName"><a href="#" class="next"><span>' + o.nextArrow + '</span></a><a href="#" class="prev"><span>' + o.prevArrow + '</span></a> ' + o.months[curMonth] + y + ' </div>';

            $this.append(table);
            $this.find('.monthName').width($this.find('.table').width());
  
            $.fn.calendarLite.next($this.find('.next'), o);
            $.fn.calendarLite.prev($this.find('.prev'), o);
        });
    };

    function loadEvents(year, month, o, callback){
        var opts = $.extend({}, $.fn.calendarLite.defaults, o);

        if(opts.eventsUrl != null){
            $this[0].innerHTML = '<div class="loader">'+opts.loader+'</div>';
            $.getJSON(opts.eventsUrl,{
                'year': year,
                'month': month
            },
            function(data){
                $.fn.calendarLite.events = data;
                $this[0].innerHTML = '';
                callback();
            });
        }
        else{
            callback();
        }
    }

    function isEventAtDay(year, month, day, o){
        var opts = $.extend({}, $.fn.calendarLite.defaults, o);

        if(opts.eventsUrl == null)
        {
            return true;
        }

        for(i = 0; i < $.fn.calendarLite.events.length; i++)
        {
            if($.fn.calendarLite.events[i].year == year
                && $.fn.calendarLite.events[i].month == month
                && $.fn.calendarLite.events[i].day == day)
                {
                return true;
            }
        }

        return false;
    }

    /**
     * Format link
     * @param {String} format
     * @param {Object} objDate
     */
    function _formatLink(format, objDate) {
        var date = objDate.getDate();
        var month = objDate.getMonth() + 1;
        var year = objDate.getFullYear();
        if (format.indexOf('{%dd}') != -1) {
            date = _formatNum(date);
        }
        if (format.indexOf('{%mm}') != -1) {
            month = _formatNum(month);
        }
        if (format.indexOf('{%yy}') != -1) {
            year = year.toString().slice(2);
        }
        var link = format.replace(/{%d(d)?}/, date).replace(/{%m(m)?}/, month).replace(/{%yy(yy)?}/, year);
        return link;
    };
    
    /**
     * Format date for link's 'rel' attribute
     * @param {String} format
     * @param {Object} objDate
     */
    function _formatDate(format, objDate) {
        var date = objDate.getDate();
        var month = objDate.getMonth();
        var year = objDate.getFullYear();
        if (format.indexOf('{%dd}') != -1) {
            date = _formatNum(date);
        }
        if (format.indexOf('{%mm}') != -1) {
            month = _formatNum(month);
        }
        if (format.indexOf('{%yy}') != -1) {
            year = year.toString().slice(2);
        }
        month++;
        var link = format.replace(/{%d(d)?}/, date).replace(/{%m(m)?}/, month).replace(/{%yy(yy)?}/, year);
        return link;
    };
    
    /**
     * Show next month
     */
    $.fn.calendarLite.next = function(button, o) {
        this.change(button, 1, o);
    };
    
    /**
     * Show previous month
     * @param {Object} button
     */
    $.fn.calendarLite.prev = function(button, o) {
        this.change(button, -1, o);
    };
    
    /**
     * Switch to another month
     * @param {Object} button
     * @param {Integer} monthDelta
     */
    $.fn.calendarLite.change = function(button, monthDelta, o) {
        var opts = $.extend({}, $.fn.calendarLite.defaults, o);
        var _self = this;
        var parent = button.parent('.monthName').parent();
        button.click(function(){
            var state = _self.getState(parent);
            var d = new Date(state[1], state[0] + monthDelta, 1);
            opts.month = d.getMonth();
            opts.year  = d.getFullYear();
            parent.calendarLite(opts);
            return false;
        });
    };
    
    /**
     * Get current calendar's state (month and year)
     */
    $.fn.calendarLite.getState = function(div) {
        var st = div.find('.state')[0].innerHTML.split('.');
        return [parseInt(st[0], 10), parseInt(st[1], 10)];
    };
    
    /**
     * Format number (pad with zero)
     * @param {Integer} num
     */
    function _formatNum(num) {
        num = parseInt(num, 10);
        if (num < 10) {
            return '0' + num;
        }
        return num;
    };
    
    /**
     * Default options
     */
    $.fn.calendarLite.defaults = {
        /**
         * Names of week's days
         */
        days: ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'],
        
        /**
         * Month names
         */
        months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август',
        'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
        
        /**
         * Link to be assigned for each link in cell:
         *   e.g.: http://snowcore.net/events/{%dd}-{%mm}-{%yyyy}
         * 
         * Possible values:
         *   {%dd} - date with leading zero
         *   {%d}  - date without leading zero
         *   {%mm} - month with leading zero
         *   {%m}  - month without leading zero
         *   {%yy} - yar (two digits)
         *   {%yyyy}  - full year (for digits)
         */
        linkFormat: null,
        
        /**
         * Format for date in 'rel' attribute (onSelect callback function retrieves this value)
         * Formatting options are the same as for 'linkFormat' option
         * Default: mm.dd.yyyy ('{%dd}.{%mm}.{%yyyy}')
         */
        dateFormat: '{%dd}.{%mm}.{%yyyy}',
        
        /**
         * Callback function, fires when user click on the cell
         * Function retrives one parameter - date
         * (in format that has been assigned by 'dateFormat' option):
         */
        onSelect: null,
        
        /**
         * When set to true, full year is displaying in the calendar caption
         */
        showYear: false,
        
        /**
         * Prev/Next arrows (you can also use &larr; and &rarr;)
         */
        prevArrow: '&laquo;',
        nextArrow: '&raquo;',

        /**
         *
         */
        loader: 'Loading...',

        /**
         *
         */
        eventsUrl: null
    };

    $.fn.calendarLite.events = new Array();
})(jQuery);