/*

BernardinaiCalendar.js
Displays event calendar with weekly event list from ICAL data.

Depends on iCalReader.js by Per-Kristian Nordnes (pk@yammin.com).
http://skogsmaskin.dyns.net/index.php?handling=vis_artikkel&art_id=7

Copyright (c) 2008 Emilis Dambauskas <emilis.d@gmail.com>

License:      
    You may use this script, as long as this header is kept intact.
    Released under the GNU General Public License Version 3 or later (the "GPL").

*/

vEvent.prototype.isWeekly = function() {
    return (this.getRuleProperties().properties.FREQ == 'WEEKLY');
}

vEvent.prototype.isMonthly = function() {
    return (this.getRuleProperties().properties.FREQ == 'MONTHLY');
}

vEvent.prototype.isFullDay = function() {
    duration = (this.getEndDate().getTime() - this.getStartDate().getTime());
    
    // 23 hours (82800 s) because of daily savings time change days.
    // + 1 because this error of calculation sometimes happens.
    return (82800000 < duration + 1);
}

vEvent.prototype.getStartTimeString = function() {
    d = this.getStartDate();
        
    if (d != 'Invalid Date')
    {
        h = d.getHours();
        if (h < 10) h = '0' + h;
        m = d.getMinutes();
        if (m < 10) m = '0' + m;
        
        return h + ':' + m;
    }
}

Date.prototype.getIso = function() {
    var y = this.getFullYear();
    var m = this.getMonth() + 1;
    var d = this.getDate();
    
    m = m < 10 ? '0'+m : m;
    d = d < 10 ? '0'+d : d;
    
    return y + '-' + m + '-' + d;
}

Date.prototype.nextDay = function() {
    this.setTime(this.getTime() + 86400000);
}


function BernardinaiCalendar()
{
    this.weekdays = new Array('Pirmadienis', 'Antradienis', 'Trečiadienis', 'Ketvirtadienis', 'Penktadienis', 'Šeštadienis', 'Sekmadienis');
    
    this.wkd_ids = new Array('MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU');
    this.wkd_days = { 'MO': 1, 'TU': 2, 'WE':3, 'TH':4, 'FR':5, 'SA':6, 'SU':0 };
    
    this.months = new Array('Sausis', 'Vasaris', 'Kovas', 'Balandis', 'Gegužė', 'Birželis', 'Liepa', 'Rugpjūtis', 'Rugsėjis', 'Spalis', 'Lapkritis', 'Gruodis');
    
    this.active_months = new Array();
}

BernardinaiCalendar.prototype = {
    
    init: function(element_id) {
        id = '#' + element_id;
        
        $(id).html(' ');
        
        $(id).append('<table id="calendar">'
            
            + '<thead><tr> <th>'
            + this.weekdays.join('</th><th>')
            + '</th> </tr></thead>'
            
            + '<tbody id="weekly">'
            + this.getSubtitle('Kiekvieną savaitę')
            + '<tr> <td id="WK_'
            + this.wkd_ids.join('"><dl></dl></td> <td id="WK_')
            + '"><dl></dl></td> </tr></tbody>'
            
            + '<tbody id="days">' + this.getDayCalendar() + '</tbody>'
            
            + '</table>');
    },
    
    getSubtitle: function(title)
    {
        return '<tr class="subtitle"><td colspan="7">' + title + '</td></tr>';
    },
    
    getDayCalendar: function()
    {
        var day_delta = 86400000;
        var d = new Date();
        var wd = d.getDay();
        
        // start from monday:
        if (wd == 0)
            d.nextDay(); //setTime(d.getTime() + day_delta);
        else if (wd > 1)
            d.setTime(d.getTime() - (wd-1) * day_delta);
        
        // create HTML:
        var html = '';
        
        var cur_month = d.getMonth();
        this.active_months.push([d.getFullYear(), d.getMonth()]);
        html += this.getSubtitle(this.months[cur_month]);
        for (i=0;i<6;i++)
        {
            html += '<tr>';
            for (j=0;j<7;j++)
            {
                if (cur_month != d.getMonth())
                {
                    for (k=j;k<7;k++) html += '<td></td>';
                    html += '</tr>';
                    cur_month = d.getMonth();
                    this.active_months.push([d.getFullYear(), d.getMonth()]);
                    html += this.getSubtitle(this.months[cur_month]);
                    html += '<tr>';
                    for (k=0;k<j;k++) html += '<td></td>';
                }
                
                html += '<td id="' + d.getIso() + '">';
                html += '<span class="date">' + d.getDate() + '</span>';
                html += '<span class="title"></span>';
                html += '<dl></dl>';
                html += '</td>';
                d.nextDay();
            }
            html += '</tr>';
        }
        return html;
    },
    
    getData: function(url)
    {
        window.bc = this;
        
        $.post(url, function(d) { window.bc.parseCal(d) });
    },
    
    parseCal: function(data)
    {  
        var reader = new iCalReader();
        reader.prepareData(data);
        reader.parse();
        reader.sort();
        
        //var cal = reader.getCalendar();
        
        var events = reader.getCalendar().getEvents();
        
        for (i in events)
        {
            if (events[i].isWeekly())
                this.addWeeklyEvent(events[i]);
            else if (events[i].isMonthly())
                this.addMonthlyEvent(events[i]);
            else if (events[i].isFullDay())
                this.addFullDayEvent(events[i]);
            else
                this.addDayEvent(events[i])
        }
        
        return true;
    },
    
    addWeeklyEvent: function(event)
    {
        var wkdays = event.getRuleProperties().properties.BYDAY.split(',');
        
        for (i in wkdays)
        {
            this.insertEventIntoDl('WK_' + wkdays[i], event);
        }
    },
    
    addMonthlyEvent: function(event)
    {
        var byday = event.getRuleProperties().properties.BYDAY;
        
        var order = byday.charAt(0);
        var day = byday.substr(1,2)
        var wkday = this.wkd_days[day];
        
        var first_day = new Date();
        for (i in this.active_months)
        {
            first_day.setFullYear(this.active_months[i][0]);
            first_day.setMonth(this.active_months[i][1]);
            first_day.setDate(1);
            
            counter = 0;
            for (j=1;j<=31;j++)
            {
                if (first_day.getDay() == wkday)
                {
                    counter++;
                    if (counter == order)
                    {
                        this.insertEventIntoDl(first_day.getIso(), event);
                        j=32;
                    }
                }
                first_day.nextDay();
            }
        }
    },
    
    addFullDayEvent: function(event)
    {
        var id = '#' + event.getStartDate().getIso();
        $(id).addClass('day_event');
        $(id + ' span.title').html(event.getProperty('SUMMARY'));
        
        $(id).addClass(this.getEventClasses(event));
    },
    
    addDayEvent: function(event)
    {
        if (event.getStartDate() != 'Invalid Date')
        {
            this.insertEventIntoDl(event.getStartDate().getIso(), event);
        }
    },
    
    insertEventIntoDl: function(parent_id, event)
    {
        if (parent_id.charAt(0) != '#')
            parent_id = '#' + parent_id;
        
        var start_time = event.getStartTimeString();
        var html = this.getEventHtml(event);
        
        var dts = $(parent_id + ' dl dt');
        for (var i=0;i<dts.length;i++)
        {
            if (start_time < dts[i].innerHTML)
                return $(dts[i]).before(html);
        }
        
        // else :
        return $(parent_id + ' dl').append(html);
    },
    
    getEventClasses: function(event)
    {
        // add aditional classes from description:
        try
        {
            var desc = event.getProperty('DESCRIPTION');
            var start = desc.indexOf('class=')
            if (start > -1)
            {
                start = start + 6;
                var finish = desc.indexOf(';', start);
                
                if (finish == -1)
                    return desc.substr(start);
                else
                    return desc.substr(start, finish - start);
            }
        }
        catch (e) { }
    },
    
    getEventHtml: function(event)
    {
        if (event.getStartDate() != 'Invalid Date')
        {
            var classes = this.getEventClasses(event)
            
            return '<dt class="' + classes + '">' + event.getStartTimeString() + '</dt><dd class="' + classes + '">' + event.getProperty('SUMMARY') + '</dd>';
        }
    },
}
