/* Copyright (c) 2011 Plus Three LLC
 * $LastChangedDate$
 * $Rev$
 * Version: 1.0.0
 */
 

(function($) {
    
    var settings = {
        url : '',
        jsonData : '',
        yearFormat : '%Y',
        monthFormat : '%b',
        dayFormat : '%d',
        template : '<div class="gc-event clearfix"><div class="gc-date">#{month}<br />#{day}</div><div class="gc-info"><a href="#{href}">#{title}</a></div></div>'
    };
    
    $.fn.googleCalendar = function(options) {
        if (options) {
            $.extend(settings, options);
        }
        
        return this.each(function() {
            googleCalendar(this);
        });
    };
    
    function googleCalendar(container) {
        $.ajax({
            url : settings.jsonData ? settings.jsonData : settings.url,
            dataType : settings.jsonData ? 'json' : 'jsonp',
            type : 'GET',
            timeout : 5000,
            error : function() {
                $(container).html('<p>Unable to retrieve calendar information.</p>');
            },
            success : function(json) {
                generateHtml(container, json);
            }
        });
    }
    
    function generateHtml(container, json) {
        $(container).html('');
        $.each(json.feed.entry, function(i, item) {
            if (typeof item.gd$when === 'undefined') return true;

            // var dt = new Date(Date.parse(item.gd$when[0].startTime));
            var dt = new Date(parseDate(item.gd$when[0].startTime));
            var href = '';
            $.each(item.link, function(j, link) {
                if (link.rel === 'alternate') {
                    href = link.href;
                    return false;
                }
            });
            var title = item.title.$t.replace(/\s/g, ' ');
            try { title = decodeURIComponent(escape(title)); } catch(err) {}
            var content = item.content.$t.replace(/\s/g, ' ');
            try { content = decodeURIComponent(escape(content)); } catch(err) {}

            var itemHtml = template(settings.template, {
                title : title,
                content : content,
                year : strftime(settings.yearFormat, dt),
                month : strftime(settings.monthFormat, dt),
                day : strftime(settings.dayFormat, dt),
                href : href
            });
            
            $(container).append(itemHtml);
        });
    }
    
    
    function template(string, values) {
        var pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
        while(match = string.match(pattern)) {
            string = string.replace(new RegExp(match[2], 'g'), values[match[3]]);
        }
        return string;
    }
    
    function parseDate(dtStr) {
        var d;
        if (d = Date.parse(dtStr)) {
            return d;
        } else {
            var struct, minutesOffset = 0, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];
            if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(dtStr))) {
                // avoid NaN dates caused by “undefined” values being passed to Date.UTC
                for (var i = 0, k; (k = numericKeys[i]); ++i) {
                    struct[k] = +struct[k] || 0;
                }
    
                // allow undefined days and months
                struct[2] = (+struct[2] || 1) - 1;
                struct[3] = +struct[3] || 1;
    
                if (struct[8] !== 'Z' && struct[9] !== undefined) {
                    minutesOffset = struct[10] * 60 + struct[11];
    
                    if (struct[9] === '+') {
                        minutesOffset = 0 - minutesOffset;
                    }
                }

                d = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
                return d;
            } else {
                return NaN;
            }
        }
    }

    function strftime(format, date, locale) {
        if(! date ) date = new Date(); // default to today
        if(! locale) locale = 'en';
        var A_values, B_values;
        if( locale == 'en' ) {
            A_values = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
            B_values = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 
                        'September', 'October', 'November', 'December'];
        } else if( locale == 'es' ) {
            A_values = ['Domingo','Lunes','Martes','MiÃ©rcoles','Jueves','Viernes','SÃ¡bado'],
            B_values = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto',
                        'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
        }

        var pattern = /%(a|A|b|B|d|m|M|H|l|p|P|y|Y)/;
        while(match = format.match(pattern)) {
            var repl;
            switch (match[1]) {
                case 'a' : repl = A_values[date.getDay()].substr(0,3); break;
                case 'A' : repl = A_values[date.getDay()]; break;
                case 'b' : repl = B_values[date.getMonth()].substr(0,3); break;
                case 'B' : repl = B_values[date.getMonth()]; break;
                case 'd' : repl = date.getDate(); break;
                case 'H' : repl = date.getHours(); break;
                case 'l' : repl = date.getHours(); if( repl > 12 ) repl = repl % 12; break;
                case 'm' : repl = date.getMonth() + 1; break;
                case 'M' : repl = date.getMinutes(); if( repl < 10 ) repl = '0' + repl; break;
                case 'p' : repl = (date.getHours() >= 12) ? 'pm' : 'am'; break;
                case 'P' : repl = (date.getHours() >= 12) ? 'PM' : 'AM'; break;
                case 'y' : repl = (date.getFullYear() + '').substr(2); break;
                case 'Y' : repl = date.getFullYear(); break;
            }
            format = format.replace(RegExp(match[0], 'g'), repl);
        }
        return format;
    }
    
})(jQuery);


