var month_names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

var current_event_id = -1;
var opacity = 0;
var fade_node = null;
var events;
var only_one_item = true;
var timeout_waiter;

var const_fade_step_time = 30;
var const_fade_step_size = 10;
var const_show_time = 2000;
var const_blank_time = 200;

var events_calendar = null;



/**
* Begins the ticker
**/
function begin_event_ticker () {
  // find the node. if its not found, come back later.
  var node = document.getElementById ('event_scroll');
  if (node == null) return;
  fade_node = node;
  
  window.setTimeout (show_event, 1000);
  
  var node = document.getElementById('calendar_events');
  var handler = new EventsCalendarHandler();
  events_calendar = new AjaxCalendar (node, 'ajax_get_events.php', handler);
}

/**
* Sets an override which is used by the mouseover system
**/
function set_event_override (event_id) {
  var node = document.getElementById ('event_hover');
  if (node == null) return;
  
  draw_event (node, event_id);
  
  fade_node.style.display = 'none';
  node.style.display = '';
}

/**
* Clears an override which is used by the mouseover system
**/
function clear_event_override () {
  var node = document.getElementById ('event_hover');
  if (node == null) return;
  
  node.style.display = 'none';
  fade_node.style.display = '';
}



function EventsCalendarHandler() {
  this.month = null;
  this.year = null;
  
  // this will be called by the calendar before the AJAX request is sent
  this.setCalendarDetails = function (month, year) {
    this.month = month;
    this.year = year;
  };
  
  this.setDefMouseEvents = function (def, index) {
    def.mouseEnter = function () {
      set_event_override (index);
    };
    def.mouseLeave = function () {
      clear_event_override ();
    };
  };
  
  this.process = function (top_node) {
    var nodes = top_node.getElementsByTagName ('day');
    var enddate = null;
    
    // Go through the days and add a day def for the days the events are on
    // Also add events for the fader
    var defs = [];
    current_event_id = -1;
    events = [];
    for (var i = 0; i < nodes.length; i++) {
      var day = parseInt(nodes[i].getAttribute ('num'), 10);
      
      // add the day def
      if (defs[day] == null || defs[day].href == '#') {
        defs[day] = new DayDefinition();
        
        if (nodes[i].getAttribute('url')) {
          defs[day].href = events_url + this.year + '-' + (this.month < 10 ? '0' : '') + this.month + '-' + (day < 10 ? '0' : '') + day;
        } else {
          defs[day].href = '#';
        }
      }
      
      // add the event to the fader
      events[i] = [day, nodes[i].firstChild.data, nodes[i].getAttribute('url')];
      
      this.setDefMouseEvents (defs[day], i);
      
      enddate = nodes[i].getAttribute('enddate');
      
      if (enddate) {
        var now = new Date();
        
        var dateparts = enddate.split ('-');
        var endyear = parseInt (dateparts[0], 10);
        var endmonth = parseInt (dateparts[1], 10);
        var endday = parseInt (dateparts[2], 10);
        
        if (endmonth > now.getMonth() + 1 || endyear > now.getFullYear()) endday = date('t');
        
        for (var x = day; x <= endday; x++) {
          if (defs[x] == null) {
            defs[x] = new DayDefinition();
            
            if (nodes[i].getAttribute('url')) {
              defs[x].href = events_url + this.year + '-' + (this.month < 10 ? '0' : '') + this.month + '-' + (x < 10 ? '0' : '') + x;
            } else {
              defs[x].href = '#';
            }
          }
        }
      }
    }
    
    // force fade out straight away
    opacity = 101;
    if (timeout_waiter != null) {
      window.clearTimeout (timeout_waiter);
      timeout_waiter = window.setTimeout (decrease_opacity, const_fade_step_size);
    }
    
    // set an ID on todays date
    var today = new Date();
    if ((this.month == today.getMonth() + 1) && (this.year == today.getFullYear())) {
      if (defs[today.getDate()] == null) {
        defs[today.getDate()] = new DayDefinition();
      }
      defs[today.getDate()].id = 'today';
    }
    
    // set the heading
    var node = document.getElementById ('calendar_name');
    node.firstChild.data = month_names[this.month - 1] + ' ' + this.year;
    
    events_calendar.draw (defs);
  }
}


/**
* Fades in an event, waits a while then fades it out
**/
function show_event () {
  // if there are not actually any events, then have tell the user
  if (events == null || events.length == 0) {
    fade_node.appendChild (document.createTextNode ('\u00A0'));   // no events message
    only_one_item = true;
    window.setTimeout (increase_opacity, const_blank_time + const_fade_step_time);
    return;
  }
  
  // choose the next event id
  current_event_id++;
  if (current_event_id >= events.length) {
    current_event_id = 0;
  }
  
  // if theres only one item we behave slightly differently
  if (events.length == 1) {
    only_one_item = true;
  } else {
    only_one_item = false;
  }
  
  draw_event (fade_node, current_event_id);
  
  // and begin the fade
  window.setTimeout (increase_opacity, const_blank_time + const_fade_step_time);
}

function draw_event (node, id) {
  // remove previous data nodes
  while (node.firstChild) {
    node.removeChild(node.firstChild);
  }
  
  // add date
  var date_text = events[id][0] + numberSuffix (events[id][0]) + ': ';
  var date_node = create_element ('b', {});
  date_node.appendChild (document.createTextNode (date_text));
  node.appendChild (date_node);
  
  // add text. will be a hyperlink if possible
  if (events[id][2] != '') {
    var link_node = create_element ('a', {'href': events[id][2]});
    link_node.appendChild (document.createTextNode (events[id][1]));
    node.appendChild (link_node);
  } else {
    node.appendChild (document.createTextNode (events[id][1]));
  }
}


/**
* Increases the opacity of the text element
**/
function increase_opacity () {
  opacity += const_fade_step_size;
  set_element_opacity (fade_node, opacity);
  
  // if we have maxed opacity, wait for a while, otherwise keep fading
  if (opacity >= 100) {
    opacity = 100;
    timeout_waiter = window.setTimeout (decrease_opacity, const_show_time);
  } else {
    window.setTimeout (increase_opacity, const_fade_step_time);
  }
}


/**
* Decreases the opacity of the text element
**/
function decrease_opacity () {
  // if we are only one item, don't start the fade straight away
  if ((opacity == 100) && only_one_item) {
    timeout_waiter = window.setTimeout (decrease_opacity, const_blank_time);
    return;
  }
  
  // otherwise fade
  opacity -= const_fade_step_size;
  set_element_opacity (fade_node, opacity);
  timeout_waiter = null;
  
  // if we have no opacity, wait for a while, otherwise keep fading
  if (opacity <= 0) {
    opacity = 0;
    window.setTimeout (show_event, const_blank_time);
  } else {
    window.setTimeout (decrease_opacity, const_fade_step_time);
  }
}


/**
* Sets the elements opacity to the specified value. Value should be a percentage with 100% is fully shown
**/
function set_element_opacity (elem, value) {
  if (elem == null) return;
  
  // IE
  elem.style.filter = 'alpha(opacity=' + value + ')';
  
  // Mozilla, Opera, Safari, etc.
  value = value / 100;
  elem.style.opacity = value;
  elem.style.MozOpacity = value;
  elem.style.KhtmlOpacity = value;
}


/**
* Gets the 'st', 'nd', 'rd' or 'th' for a number
**/
function numberSuffix (num) {
  num = String(num);
  
  firstTwoDigits = num.substr(-(Math.min(num.length, 2)));
  
  if (firstTwoDigits > 3 && firstTwoDigits < 21) {
    return "th";
    
  } else {
    var suffixes = ["th", "st", "nd", "rd", "th"];
    return suffixes[Math.min (Number(num) % 10, 4)];
  }
}



/**
* Functions to make MSIE sane
**/
var is_msie = false;
if (navigator.userAgent.match ('MSIE') !== null) is_msie = true;

function create_element (tag_name, attribs) {
  var element = null;
  
  tag_name = String (tag_name);
  tag_name = tag_name.toLowerCase ();
  
  // IE is broken with many elements but its non-W3C methods seem to work
  if (is_msie) {
    var tag_text;
    tag_text = '<' + tag_name;
    for (var key in attribs) {
      tag_text += ' ' + String (key) + '="' + String (attribs[key]) + '"';
    }
    tag_text += '>';
    element = document.createElement (tag_text);
    
  } else {
    element = document.createElement (tag_name);
    for (var key in attribs) {
      element.setAttribute (String (key), String (attribs[key]));
    }
  }
  
  return element;
}
