//if (top.myBrowser.needsXMLHttpRequestVariable) {var XMLHttpRequest;}

function GoogleCalendar(url, useJson, jsonElementId) {
  this.type = "Google Calendar Feed";
  this.title = ["<img src='loading.gif'/> Loading Events ..."];
  this.time = null;
  this.repeat = 0;
  this.calUrl = url;
  this.useJson = useJson;
  this.jsonElementId = jsonElementId;
    
  
  this.requestCalendar = function() {
    if (this.useJson) {
      GoogleCalendar.objects[this.jsonElementId] = this;
      eval("GoogleCalendar." + this.jsonElementId + 
           "=function(root) {GoogleCalendar.objects['" +
           this.jsonElementId + "'].jsonCallback(root)}");
      GoogleCalendar.requestCalendarJson(this.calUrl, $(this.jsonElementId), 
        "GoogleCalendar." + this.jsonElementId);  
    }
    else {
      this.requestCalendarAjax();
    }
  }
  
  this.jsonCallback = function(root) {
    var result = new Object();
    result.title = ["Loading failed: <button onclick='retry()'>Retry</button>"];
    result.type = ["Calendar"];
    if (root != null) {
      result = GoogleCalendar.parseCalendarJson(root);
    }  
    this.parseResult(result);    
  }
    
  this.requestCalendarAjax = function() {  
    var request = new XMLHttpRequest();
    request._self = this;
    var index = this.calUrl.lastIndexOf("/");
    if (index > 0) {
      this.calUrl = this.calUrl.substring(0, index) + "/full";
    }
    request.overrideMimeType("text/xml");
    request.open("GET", this.calUrl + "?orderby=starttime&max-results=5&singleevents=true&sortorder=ascending&futureevents=true", true);
    request.onreadystatechange = function () {
      if (request.readyState == 4) {
        if (request.status == 200) {
          var root = request.responseXML;
          var result = GoogleCalendar.parseCalendarXml(root);
          request._self.parseResult(result);
        }
        else {
          if (request._self.onerror) {
            request._self.onerror();
          }
        }
      }
    }
    request.send(null);
  }
  
  this.parseResult = function(result) {
    if (result.icon) {
      this.icon = result.icon;
    }
    else {
      this.icon = null;
    }
    this.type = result.type;
    this.title = result.title;
    this.time = result.time;
    if (result.url) {
      this.url = result.url;
    }
    else {
      this.url = null;
    }  
    if (this.onload) {
      for (var i = 0; i < this.onload.length; i++) {
        this.onload[i]();      	
      }
    }    
  }
  
  this.onload = new Array();
 
  this.onerror = new Array();
  
  this.setTitle = function(title) {
    this.title = title;
  }
  
  this.getTime = function(index) {
    if (this.time) {
      return this.time[index];
    }
    return this.time;  
  }
  
  this.setTime = function(time) {
    this.time = time;
  }
  
  this.setRepeat = function(repeat) {
    this.repeat = repeat;
  }
  
  this.hasNextTime = function() {
    return true;
  }
  
  this.nextTime = function() {
    this.requestCalendar();
  }
}

GoogleCalendar.parseCalendarXml = function(root) {
  var result = new Object();
  var feed = root.getElementsByTagName("feed")[0];
  var titles = feed.getElementsByTagName("title");
  if (titles != null && titles.length > 0) {
    result.type = feed.getElementsByTagName("title")[0].firstChild.data;
  }
  else {
    result.type = "Calendar";
    //Safari fix
    for (var i = 0; i < feed.childNodes.length; i++) {
 	    if (feed.childNodes[i].nodeName == "title") {
        result.type = feed.childNodes[i].firstChild.data;
        break;
 	    }
    }
  }           
  var entries = feed.getElementsByTagName("entry");
  if (entries.length == 0) {
    result.time = null;
    result.title = ["No Event"];
    return result;
  }
  var index = 0;
  var nextEntry = null;
  var now = new Date();
  do {
    var entry = entries[index];
    var when = entry.getElementsByTagName("when")[0];
    var date = when.getAttribute("startTime");
    var time = GoogleCalendar.parseDate(date)
    if (time >now && (!nextEntry || nextEntry.time > time)) {
      nextEntry = entry;
      nextEntry.time = time;
    }
    index++;
  }
  while (time < now && index < entries.length);
  if (!nextEntry) {
    result.time = null;
    result.title = ["No future Events"];
    return result;
  }
  result.time = nextEntry.time;
  var titles = nextEntry.getElementsByTagName("title");
  if (titles != null && titles.length > 0) {
    result.title = nextEntry.getElementsByTagName("title")[0].firstChild.data;
  }
  else {
    result.title = "Calendar Event";
    //Safari fix
    for (var i = 0; i < nextEntry.childNodes.length; i++) {
 	    if (nextEntry.childNodes[i].nodeName == "title") {
        result.title = nextEntry.childNodes[i].firstChild.data;
        break;
 	    }
    }
  }  
  var links = nextEntry.getElementsByTagName("link");
  if (links.length > 0) {
    for (var i = 0; i < links.length; i++) {
    	var link = links[i];
    	if (link.getAttribute("rel") == "alternate") {
        result.url = link.getAttribute("href");  	  
    	}
    	if (link.getAttribute("rel") == "http://schemas.google.com/gCal/2005/webContent") {
    	  result.icon = link.getAttribute("href");
    	}
    }
  }
  else {
    for (var i = 0; i < nextEntry.childNodes.length; i++) {
    	if (nextEntry.childNodes[i].nodeName == "link") {
    	  var link = nextEntry.childNodes[i];
    	  if (link.getAttribute("rel") == "alternate") {
          result.url = link.getAttribute("href");  	  
    	  }
    	  if (link.getAttribute("rel") == "http://schemas.google.com/gCal/2005/webContent") {
    	    result.icon = link.getAttribute("href");
    	  }
    	}
    }    
  }
  return result;
}

GoogleCalendar.parseCalendarJson = function(root) {
  var result = new Object();
  var feed = root.feed;          
  result.type = feed.title.$t;
  var entries = feed.entry;
  if (!entries || entries.length == 0) {
    result.time = null;
    result.title = ["No Events"];
    return result;
  }
  result.time = new Array();
  result.title = new Array();//"No future Events";
  result.url = new Array();
  result.icon = new Array();
  var now = new Date();
  var nextEntry = getNextEntry(entries, now, -1);
  while (nextEntry && result.time.length < 10) {
    result.time.push(nextEntry.time);
    result.title.push(nextEntry.title.$t);
    var links = nextEntry.link;
    for (var i = 0; i < links.length; i++) {
    	var link = links[i];
    	if (link.rel == "alternate") {
        result.url.push(link.href);  	  
    	}
    	if (link.rel == "http://schemas.google.com/gCal/2005/webContent") {
    	  result.icon.push(link.href);
    	}
    }
    now = nextEntry.time;
    nextEntry = getNextEntry(entries, now, nextEntry.index);
    //console.log(now);
  }
  if (result.time.length == 0) {
    result.time = null;
    result.title = ["No future Events"];
    result.url = null;
    result.icon = null;
  }
  return result
}

function getNextEntry(entries, now, lastIndex) {
  var index = lastIndex + 1;
  var nextEntry = null;
  do {
    if (index >= entries.length) {
      break;
    }
    var entry = entries[index];
    var when = entry.gd$when[0];
    var date = when.startTime;
    var time = GoogleCalendar.parseDate(date)
    //alert(date + " " + time);
    if (time >= now && (!nextEntry || nextEntry.time > time)) {
      nextEntry = entry;
      nextEntry.time = time;
      nextEntry.index = index;
    }
    index++;
  }
  while (index < entries.length);
  return nextEntry;
}

GoogleCalendar.requestCalendarJson = function(url, element, callback) {
  var index = url.lastIndexOf("/");
  if (index > 0) {
    url = url.substring(0, index) + "/full";
  }
  var script = element;
  script.innerHTML = "";
  var inside = document.createElement("script");
  inside.src = url + "?alt=json-in-script&orderby=starttime&max-results=25&singleevents=true&sortorder=ascending&futureevents=true&callback=" + encodeURIComponent(callback);
  script.appendChild(inside);
  inside.onerror = function() {
    eval(callback + "(null)");;
  }
}

GoogleCalendar.parseDate = function(date) {
  var time = new Date();
  time.setUTCFullYear(parseInt(date.substring(0, 4), 10));
  time.setUTCMonth(parseInt(date.substring(5, 7), 10) - 1);
  time.setUTCDate(parseInt(date.substring(8, 10), 10));
  if (date.length > 11) {
    time.setUTCHours(parseInt(date.substring(11, 13), 10))
    time.setUTCMinutes(parseInt(date.substring(14, 16), 10));
  }
  else {
    time.setUTCHours(0);
    time.setUTCMinutes(0);            
  }          
  time.setUTCSeconds(0);
  time.setUTCMilliseconds(0);
  if (date.length > 23) {
    var zone = parseInt(date.substring(23, 26), 10);
    time.setUTCHours(time.getUTCHours() - zone);
  }
  else {
    time.setUTCMinutes(time.getUTCMinutes() + time.getTimezoneOffset());
  }
  return time;  
}

GoogleCalendar.objects = new Object();

