function Calendar(name, id, callback)
{
    this.name = name;
    this.id = id;
    this.callback = callback;
    this.date = new Date();
    this.ends = new Date();
    this.show = new Date();
    this.months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
    this.weekdays = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'];
    this.weekdates = [];
    this.period = 'day';

    this.load = function()
    {
        this.setDate(this.date.getFullYear(), this.date.getMonth()+1, this.date.getDate());

        // TODO: Load ALL calendar notes into an array then use <acronym>
    }

    this.display = function()
    {
        var el = document.getElementById(this.id);
        if (el) el.innerHTML = this.getHtml();
    }

    this.showDate = function(year, month, day)
    {
        if (month == 0)
        {
            year--;
            month = 12;
        }
        this.show = new Date(year, month-1, day, 0, 0, 0);
        this.display();
    }

    this.setDate = function(year, month, day)
    {
        this.period = 'day';
        if (day == 40)
        {
            this.period = 'month';
            day = 1;
        }
        else if (day > 40)
        {
            this.period = 'week';
            day -= 50;
        }
        this.date = new Date(year, month-1, day);

        if (this.period == 'month')
            this.ends = new Date(year, month, day, 0, 0, -1);
        else if (this.period == 'week')
            this.ends = new Date(year, month-1, day+7, 0, 0, -1);
        else // 'day'
            this.ends = new Date(year, month-1, day+1, 0, 0, -1);

        this.showDate(year, month, day);
        this.callback();
    }

    this.getWeeks = function()
    {
        var html = '';
        var date = new Date(this.show);
        var current = date.getMonth();
        var weeks = [];
        var weeknum = 0;
        for (var days = 1; days <= 31; days++)
        {
            date.setDate(days);
            if (date.getMonth() > current) break;
            if (!weeks[weeknum]) weeks[weeknum] = [];
            var day = date.getDay() - 1;
            if (day < 0) day = 6;
            if (day == 0) this.weekdates[weeknum] = date.getDate();
            if (1 == (weeks[weeknum][day] = date.getDate())) this.weekdates[weeknum] = 1-day;
            if (day == 6) weeknum++;
        }
        return weeks;
    }

    this.getHtml = function()
    {
        var html = '<table class="calTable" cellPadding="2" cellSpacing="1">\n';
        html += '<tr><th class="calMonth"' + this.getEvents(this.show.getFullYear(), this.show.getMonth(), 40, true) + '>Month</th>';
        html += '<th class="calMonth"' + this.getEvents(this.show.getFullYear(), this.show.getMonth()-1, 1, false) + '>&lt;&lt;</th>';
        html += '<th class="calTitle" colspan="5">' + this.months[this.show.getMonth()] + ' ' + this.show.getFullYear() + '</th>';
        html += '<th class="calMonth"' + this.getEvents(this.show.getFullYear(), this.show.getMonth()+1, 1, false) + '>&gt;&gt;</th></tr>\n';
        html += '<tr>';
        var today = new Date();
        html += '<th class="calToday"' + this.getEvents(today.getFullYear(), today.getMonth(), today.getDate(), true) + '>Today</th>';
        for (var day = 0; day < 7; day++)
        {
            html += '<th class="calWeekDay">' + this.weekdays[day] + '</th>';
        }
        html += '</tr>\n';
        var weeks = this.getWeeks();
        for (var weeknum in weeks)
        {
            if (isNaN(weeknum)) continue;
            var week = weeks[weeknum];
            html += '<tr>';
            html += '<td class="calWeek"' + this.getEvents(this.show.getFullYear(), this.show.getMonth(), this.weekdates[weeknum]+50, true) + '>Week</td>';
            for (var day = 0; day < 7; day++)
            {
                if (!week[day]) week[day] = this.weekdates[weeknum] + day;
                var date = new Date(this.show.getFullYear(), this.show.getMonth(), week[day], 0, 0, 0);
                var events = this.getEvents(this.show.getFullYear(), this.show.getMonth(), week[day], true);
                var klass = (date.getTime() >= this.date.getTime() && date.getTime() < this.ends.getTime()) ? 'calSelected' : (day < 5 ? 'calDay' : 'calWeekEnd');
                html += '<td class="' + klass + '" ' + events + '>' + date.getDate() + '</td>';
            }
            html += '</tr>\n';
        }
        html += '</table>\n';
        this.show.setDate(1);
        return html;
    }

    this.getEvents = function(year, month, day, do_set)
    {
        var method = do_set ? '.setDate' : '.showDate';
        var events = ' onClick="' + this.name + method + '(' + year + ',' + (month+1) + ',' + day + ')"';
        events += ' onMouseOver="this.oldClassName=this.className;this.className=\'calMouseOver\'"';
        events += ' onMouseOut="if (this.oldClassName) this.className=this.oldClassName"';
        return events;
    }
}
