(function($){

    var ns = $.monthpicker = $.monthpicker || {};
    var weekStartsOnMonday = true;

    var renderMonth = function(data) {
        var t = '<div class="monthpicker-body">';

        var wlen = data.length;
        for (var x = 0; x < wlen; x++) {
            var w = data[x];
            t += '<div class="monthpicker-week">';
            var dlen = w.length;
            for (var y = 0; y < dlen; y++) {
                var hasDay = (w[y] === false ? false : true);
                t += '<div class="monthpicker-day' + (hasDay ? (w[y][1] ? ' monthpicker-hasitem' : '') : ' monthpicker-noday') + '">';
                if (hasDay) {
                    t += w[y][0];
                }
                t += '</div>';
            }
            t += '</div>';
        }

        t += '</div>';
        return t;
    };

    var shiftMonthDataToMonday = function(weeks) {
        var nweeks = [[false, false, false, false, false, false, false]];
        var wlen = weeks.length;

        var placeData = function(w, d, data) {
            w++; // get one week ahead
            d--; // get day back;
            if (d < 0) {
                d = 6;
                w--;
            }
            nweeks[w] = nweeks[w] || [];
            nweeks[w][d] = data;
        };

        for (var w = 0; w < wlen; w++) {
            for (var d = 0; d < 7; d++) {
                placeData(w, d, weeks[w][d]);
            }
        }

        // check on last week, we should fill it up to have a complete structure
        var last = nweeks[nweeks.length - 1];
        var len = last.length;
        for (var x = len; x < 7; x++) {
            last[x] = false;
        }

        // remove first week if its empty
        var first = nweeks[0];
        if (first[0] === false && first[1] === false && first[2] === false && first[3] === false &&
            first[4] === false && first[5] === false && first[6] === false) {
            nweeks.shift();
        }

        // remove last week if its empty
        if (last[0] === false && last[1] === false && last[2] === false && last[3] === false &&
            last[4] === false && last[5] === false && last[6] === false) {
            nweeks.pop();
        }

        return nweeks;
    };

    var getMonthData = function(month, year, dateElements) {

        // array containing date strings (dd-mm-yyyy) for days that have 'items'
        var hasItemDates = [];

        // collect all the dates from the elements passed to fill the has items array
        $(dateElements).each(function(){
            var date = $(this).text();
            hasItemDates.push(date);
        });

        // create a date object based on the passed day and month
        var startDate = new Date(year, month, 1);

        // get the day of the week the first day of this month starts on
        var startDayOfWeek = startDate.getDay();

        /*var maxday = (function(){
            var day = 28;
            var d = new Date(year, month, day);
            while (d.getMonth() == month) {
                day++;
                d = new Date(year, month, day);
            }
            return --day;
        })();*/

        var weeks = []; // array that contains the weeks
        var cweek = 0; // week counter
        var cday = 0; // day of the week counter
        weeks[0] = []; // initialize first week

        // fill up the first week's array until the day that the month starts
        // this increments the day counter
        for (; cday < startDayOfWeek; cday++) {
            weeks[0][cday] = false;
        }

        currentMonth = month; // keep track of the month while looping
        currentDay = 1; // the first of the month

        // fill up the weeks array while we stay in the current month
        while (currentMonth == month) {

            // get the date string that we will match on within the has items array
            var dateString = (currentDay < 10 ? '0' + currentDay : currentDay) + '-' + (month + 1) + '-' + year;
            var hasItem = $.inArray(dateString, hasItemDates) != -1 ? true : false;

            // store date info
            weeks[cweek][cday] = [currentDay, hasItem];

            currentDay++; // next day please
            cday++; // increment the day of the week counter

            // get new month
            currentMonth = new Date(year, month, currentDay).getMonth();

            // there are just seven days in a week
            if (cday > 6) {
                cday = 0;
                cweek++;
                weeks[cweek] = []; // initialize next week
            }
        }

        // fill up the remaining days of the last week, in case the
        // month did not end on a saturday
        if (cday < 7) {
            for (;cday < 7; cday++) {
                weeks[cweek][cday] = false;
            }
        }

        if (weekStartsOnMonday) weeks = shiftMonthDataToMonday(weeks);

        // return the data
        return weeks;
    };

    var init = function(el) {
        // get the month and year based on a "mm-yyyy" format
        var t = $(el).text().split('-');
        var d = new Date(t[1], t[0] - 1, 1);
        var month = d.getMonth();
        var year = d.getFullYear();

        var hasItemElements = $('.monthpicker-date');
        var data = getMonthData(month, year, hasItemElements);
        var html = renderMonth(data);
        $(el).after(html);
    };

    $.fn.extend({
        monthpicker : function() {
            $(this).each(function(){
                init(this);
            });
            return this;
        }
    });

})(jQuery);
