  function AjaxRequest(u, cb) {
    this.callback = cb;
    this.url = u;
  }

  AjaxRequest.prototype.send = function() {
    this.request = (window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : null));
    var that = this;
    this.request.onreadystatechange = function() {
      that.callback(that);
    }
    this.request.open("GET", this.url, true);
    this.request.send(null);
  }

  function hasEvent(day, events) {
    for (var i=0;i<events.length;++i) {
      if (day == DateFormatter.format(new Date(events[i].startDate), 'j')) {
        return true;
      }
    }
    return false;
  }

  function eventsReceived(req) {
    var request = req.request;
    if (request.readyState == 4) {

      if (request.status == 200) {
        var resultText = request.responseText;
        var result = eval('(' + resultText + ')');

        var x = document.getElementById(req.resultDiv);
        x.innerHTML = "";
        x.style.display = 'block';
        if (req.renderCalendar) {
          var prevMonth = DateFormatter.format(new Date(result.prevMonth), "Ym");
          var month = DateFormatter.format(new Date(result.month), "Ym");
          var monthStr = DateFormatter.format(new Date(result.month), "F Y");
          var nextMonth = DateFormatter.format(new Date(result.nextMonth), "Ym");

          var code = '<table class="cal" cellspacing="0" border="0">';

          // days header
          code += '<tr>';
          for (i=0;i<7;++i) {
            code += '<th class="cal_day_title">' + DateFormatter.weekFull_nl[i].substr(0, 1) + '</td>';
          }
          code += '</tr>';

          var day = 1;
          var startWeekDay = DateFormatter.startWeekDay(new Date(result.month));
          var lastDayOfMonth = DateFormatter.lastDayOfMonth(new Date(result.month));

          // first row of days
          code += '<tr>';
          for (i=0;i<7;++i) {
            if (i < startWeekDay) {
              code += '<td class="cal_day">&nbsp;</td>';
            } else {
              code += getCalCell(req, day, month, result);
              day++;
            }
          }
          code += '</tr>';

          // middle days
          while (day + 7 <= lastDayOfMonth) {
            code += '<tr>';
            for (i=0;i<7;++i) {
              
              code += getCalCell(req, day, month, result);
              day++;
            }
            code += '</tr>';
          }

          // last row of days
          finalEmptyFields = day - lastDayOfMonth + 6;
          code += '<tr>';
          while (day <= lastDayOfMonth) {
            code += getCalCell(req, day, month, result);
            day++;
          }
          for (i=0;i<finalEmptyFields;++i) {
            code += '<td class="cal_day">&nbsp;</td>';
          }
          code += '</tr>';

          // navigation
          code += '<tr><td colspan="7" class="cal_nav">';
          code += '<a class="cal_nav" href="#' + req.calendarAnchorName + '" onclick="';
          /* Test if it is a calendar on the homepage. If it is, the previous and next month links must use the renderHomeCalendar function. */
          if (req.homeCalendar) code += 'renderHomeCalendar';
          else code += 'renderCalendar';
          code += '(\'' + req.resultDiv + '\', \'' + req.targetDiv + '\', \'' + req.targetDivToHide + '\', \'' + req.calendarAnchorName + '\', \'' + req.eventsAnchorName + '\', \'' + prevMonth + '\');return false;">&laquo;</a>';
          code += '<span class="cal_cur_date">' + monthStr + '</span>';
          code += '<a class="cal_nav" href="#' + req.calendarAnchorName + '" onclick="';
          /* Test if it is a calendar on the homepage. If it is, the previous and next month links must use the renderHomeCalendar function. */
          if (req.homeCalendar) code += 'renderHomeCalendar';
          else code += 'renderCalendar';
          code += '(\'' + req.resultDiv + '\', \'' + req.targetDiv + '\', \'' + req.targetDivToHide + '\', \'' + req.calendarAnchorName + '\', \'' + req.eventsAnchorName + '\', \'' + nextMonth + '\');return false;">&raquo;</a>';
          code += '</td></tr>';
          code += '</table>';
          x.innerHTML = code;
        } else {
          if (result.events.length == 0) {
            x.innerHTML = "Geen events gevonden";
          } 
          else {
            var baseContent = document.getElementById(req.sourceDiv).innerHTML;
            if (req.getEvents && (req.homeCalendar == null || !req.homeCalendar)) x.innerHTML = x.innerHTML + "<h2>Overzicht van de komende "+ result.events.length +" evenementen</h2>";
            for (i=0;i<result.events.length;++i) {
              var line = baseContent;
              line = line.replace(/@ID@/g, result.events[i].id);
              line = line.replace(/@TITLE@/g, result.events[i].title);
              line = line.replace(/@SUMMARY@/g, result.events[i].summary);
              line = line.replace(/@CONTENT@/g, result.events[i].content);
              line = line.replace(/@LOCATION@/g, result.events[i].location);
              line = line.replace(/@STARTDATE@/g, DateFormatter.format(new Date(result.events[i].startDate), 'd/m/Y H:i'));
              line = line.replace(/@ENDDATE@/g, DateFormatter.format(new Date(result.events[i].endDate), 'd/m/Y H:i'));
              line = line.replace(/@ORGANIZER@/g, result.events[i].organizer);
              x.innerHTML = x.innerHTML + line;
            }
            if (req.daySelection) {
              /* On the homepage the link must 'close' (hide with css) the eventoverview, the normal homepage content must be set visible again.
              If not on the homepage (so in kalender.jsp) it's enough to just re-call the getEvents function with the appropiate parameters.
              */
              if (req.homeCalendar) x.innerHTML += "<br/>\n<a href=\"#\" onclick=\"document.getElementById(\'"+req.resultDiv+"\').style.display=\'none\';document.getElementById(\'newsblock_container\').style.display=\'block\';return false;\">Sluiten</a>";
              else x.innerHTML += "<br/>\n<a href=\"#\" onclick=\"getEvents('"+req.resultDiv+"', '"+req.sourceDiv+"', 'today', '', 5);return false;\">Terug naar overzicht</a>";
            }
          }
        }
      } else {
        var x = document.getElementById(req.resultDiv);
        x.innerHTML = "";
        x.style.display = 'block';
        x.innerHTML = "Er is een probleem opgetreden in de eventmanager.";
      }
    }
  }
  
  /*This function is called for every day in the calendar. It returns the code for the day-cell in the calendar table. If on the 
  homepage a parameter is added to the getEvents function call in order to 'remember' we are on the homepage.  
  */
  function getCalCell(req, day, month, result){
    var code = "";
    if (hasEvent(day, result.events)) {
      code += '<td class="cal_active"><a class="cal_active" href="#' + req.eventsAnchorName + '" onclick="getEvents(\'' +  req.targetDiv + '\',\''+req.targetDivToHide+'\', \'' + month + day + '\', \'' + month + (day + 1);
      if (req.homeCalendar) code += '\', \'\', \'true';
      code += '\');';
      if (req.homeCalendar) code += 'document.getElementById(\'newsblock_container\').style.display=\'none\';';
      code += 'return false;">' + day + '</a></td>';
    } 
    else {
      code += '<td class="cal_day">' + day + '</td>';
    }
    return code;    
  }

  function eventReceived(req) {
    var request = req.request;
    if (request.readyState == 4) {

      if (request.status == 200) {
        var resultText = request.responseText;
        var result = eval('(' + resultText + ')');

        if (req.customCallback) {
          req.customCallback(result.event);
        }

        var x = document.getElementById(req.resultDiv);
        x.innerHTML = "";
        x.style.display = 'block';
        var baseContent = document.getElementById(req.sourceDiv).innerHTML;
        var line = baseContent;
        line = line.replace(/@ID@/g, result.event.id);
        line = line.replace(/@TITLE@/g, result.event.title);
        line = line.replace(/@SUMMARY@/g, result.event.summary);
        line = line.replace(/@CONTENT@/g, result.event.content);
        line = line.replace(/@LOCATION@/g, result.event.location);
        line = line.replace(/@STARTDATE@/g, DateFormatter.format(new Date(result.event.startDate), 'd/m/Y H:i'));
        line = line.replace(/@ENDDATE@/g, DateFormatter.format(new Date(result.event.endDate), 'd/m/Y H:i'));
        line = line.replace(/@ORGANIZER@/g, result.event.organizer);
        x.innerHTML = line;
      } else {
        var x = document.getElementById(req.resultDiv);
        x.innerHTML = "";
        x.style.display = 'block';
        x.innerHTML = "Er is een probleem opgetreden in de eventmanager.";
      }
    }
  }

  /*The original function was modified by adding the parameter 'home'. This extra parameter makes it possible to set a request 
  parameter used by the logic that handles the request result later on 
  */
  function getEvents(outputDiv, templateDiv, from, to, max, home) {
    var url = '/gboutersem/servlet/jsonevent?method=getEvents';
    if (from) {
      url += '&from=' + from;
    }
    if (to) {
      url += '&to=' + to;
    }
    if (max) {
      url += '&max=' + max;
    }

    var ajax = new AjaxRequest(url, eventsReceived);
    ajax.resultDiv = outputDiv;
    ajax.sourceDiv = templateDiv;
    ajax.renderCalendar = false;        
    
    if (to){
      ajax.daySelection = true;
    }
    else ajax.getEvents = true;
    if (home) ajax.homeCalendar = true;
    else ajax.homeCalendar = false;
    
    ajax.send();
  }

  function getRenderCalendarRequest(div, targetDiv, targetDivToHide, calendarAnchorName, eventsAnchorName, month){
    var url;
    url = '/gboutersem/servlet/jsonevent?method=getEvents&month=' + month;
    var ajax = new AjaxRequest(url, eventsReceived);
    ajax.resultDiv = div;
    ajax.targetDiv = targetDiv;
    ajax.targetDivToHide = targetDivToHide;
    ajax.calendarAnchorName = calendarAnchorName;
    ajax.eventsAnchorName = eventsAnchorName;
    ajax.renderCalendar = true;
    return ajax;
  }

  function renderCalendar(div, targetDiv, targetDivToHide, calendarAnchorName, eventsAnchorName, month) {
    var ajax = getRenderCalendarRequest(div, targetDiv, targetDivToHide, calendarAnchorName, eventsAnchorName, month);
    ajax.send();
  }
  
  function renderHomeCalendar(div, targetDiv, targetDivToHide, calendarAnchorName, eventsAnchorName, month) {
    var ajax = getRenderCalendarRequest(div, targetDiv, targetDivToHide, calendarAnchorName, eventsAnchorName, month);
    ajax.homeCalendar = true;
    ajax.send();
  }

  function getEvent(id, outputDiv, templateDiv, customCallback) {
    var url;
    url = '/gboutersem/servlet/jsonevent?method=getEvent&id=' + id;
    var ajax = new AjaxRequest(url, eventReceived);
    ajax.resultDiv = outputDiv;
    ajax.sourceDiv = templateDiv;
    ajax.customCallback = customCallback;
    ajax.send();
  }

