if(!MooTools){
  throw 'ContentSlider depends on the MooTools framework version '+MooTools.version+'.';
}

var EventCalendar = new Class({

  options: {
    event_height: 25
  },

  wrapper: null,
  event_calendar: null,
  event_wrappers: [],
  event_rolloversc: [],
  event_wrapper: null,
  event_rollovers: null,
  rollover_fx: null,
  calendar_key: null,
  events: [],
  key_size: null,
  key_scroll_size: null,
  key_fx: null,
/**
 * event[0] - event div object
 * event[1] - event_id
 * event[2] - month
 * event[3] - day
 * event[4] - event duration
 * event[5] - vertical index
 *
 */
  cell_widths: [],
  types_visible: [],
  events_visible: 'published',

  initialize: function(wrapper, key, type_visibility) {
    this.wrapper = $(wrapper);
    this.calendar_key = $(key);
    // find calendar
    this.event_calendar = $E('table');
    details = this.event_calendar.getAttribute('id').split("_");
    this.year = parseInt(details[1], 10);
    this.types_visible = type_visibility;

    // find event wrapper
    this.event_wrappers['published'] = $('published_event_wrapper');

    // find event rollovers
    this.event_rolloversc['published'] = $('published_event_rollovers');

    // add events to key items
    this.addKeyEvents();

    // add events to table
    this.addTableEvents();

    // add mcell events to rollovers
    this.addCellEvents()

    // position event wrapper
    this.positionEventWrapper();

    // find out the columns widths of the table
    this.getColumnWidths();

    this.setVisible(this.events_visible);
  },

  getDayPosition: function(day, month) {
    day = $E('#day_'+day+"_"+month, this.event_calendar);
    if (day) {
      pos = day.getPosition();
      if (!window.gecko) {
        pos.x++;
        pos.y++;
      }
      return pos;
    }
    return null;
  },

  parseEvents: function() {
    // find all events in the events wrapper
    event_divs = $ES('div', this.event_wrapper);

    // add them to the events array with their details easily accessible
    event_divs.each(function(event) {
      details = event.getAttribute('id').split("_");
      this.events.include([event, parseInt(details[1], 10), parseInt(details[2], 10), parseInt(details[3], 10), parseInt(details[4], 10), parseInt(details[5], 10)]);
      if (!event.hasClass('event_changeover')) {  // don't add any events if no event_id
        // add rollovers
        event.addEvent('mouseenter', function(e) {
          e = new Event(e).stop();
          tar = e.target;
          if (tar.tagName == 'P') {
            tar = tar.parentNode;
          }
          details = tar.getAttribute('id').split("_");
          // show the rollover for this element
          this.showRollover(tar, details[1]);
          // highlight any other elements with this event_id
          this.highlightEvents(tar, details[1]);
        }.bind(this));

        if (!this.getRollover(details[1])) {
          event.addEvent('mouseleave', function(e) {
            e = new Event(e).stop();
            tar = e.target;
            if (tar.tagName == 'P') {
              tar = tar.parentNode;
            }
            tar.setStyle('cursor', 'auto');
            details = tar.getAttribute('id').split("_");
            // highlight any other elements with this event_id
            this.unHighlightEvents(details[1]);
          }.bind(this));
        }
      }
      else {  // set height of changeover event
        cell = this.getCell(details[3], details[2]);
        event_height = cell.offsetHeight-1;
        event.setStyle('height', event_height+'px');
        event_desc = $E('p', event);
        event_desc.setStyle('margin-top', (event_height-event_desc.offsetHeight)/2+'px')
      }
    }.bind(this));
  },

  positionEventWrapper: function() {
    pos = this.event_calendar.getPosition();
    this.event_wrappers['published'].setStyle('left', "0px");
    this.event_wrappers['published'].setStyle('top', "-"+pos.y+"px");
    this.event_rolloversc['published'].setStyle('left', "0px");
    this.event_rolloversc['published'].setStyle('top', "-"+pos.y+"px");
  },

  positionEvents: function() {
    this.events.each(function(event) {
      pos = this.getDayPosition(event[2], event[3]);
      event[0].setStyle('left', pos.x+"px");
      event[0].setStyle('top', Math.round(pos.y+event[5]*this.options.event_height)+"px");
    }.bind(this));
  },

  resizeEvents: function() {
    this.events.each(function(event) {
      event[0].setStyle('width', this.getEventWidth(event[3], event[2], event[4])+"px");
    }.bind(this));
  },

  resizeCalendar: function() {
    this.positionEvents();
    this.getColumnWidths();
    this.resizeEvents();
  },

  highlightEvents: function(src, event_id) {
    postfix = this.findPostfix(src);
    this.events.each(function(event) {
      if (event[1] == event_id) {
        event[0].removeClass('event_'+postfix);
        event[0].addClass('highlight_'+postfix);
      }
    }.bind(this));
  },

  unHighlightEvents: function(event_id) {
    // find an event with this
    postfix = null;
    this.events.each(function(event) {
      if (event[1] == event_id) {
        if (!postfix) {
          postfix = this.findPostfix(event[0]);
        }
        event[0].removeClass('highlight_'+postfix);
        event[0].addClass('event_'+postfix);
      }
    }.bind(this));
  },

  findPostfix: function(el) {
    if (el.hasClass('event_exhibition') || el.hasClass('highlight_exhibition')) {
      return 'exhibition';
    }
    else if (el.hasClass('event_pprogram') || el.hasClass('highlight_pprogram')) {
      return 'pprogram';
    }
    else if (el.hasClass('event_gprogram') || el.hasClass('highlight_gprogram')) {
      return 'gprogram';
    }
    return 'external';
  },

  showRollover: function(tar, event_id) {
    this.hideRollovers();
    if (event_id) {
      // get contents of target
      rollover = this.getRollover(event_id);
      if (rollover) {
        header_upper = $E('.header_info_upper', rollover);
        pos = tar.getPosition();
        size = tar.getScrollSize();

        // work out if it should pop down or pop up.
        details = tar.getAttribute('id').split("_");
        day_cell = this.getCell(details[3], details[2]);

        // which row does month start
        row_index = day_cell.parentNode.sectionRowIndex;

        // pop up
        this.rollover_fx[details[1]].cancel();
        this.rollover_fx['el_'+details[1]].cancel();
        rollover.setStyles({position: 'absolute',
                            left: pos.x,
                            width: size.x,
                            display: 'block'});
        rollover.setStyle('top', pos.y);

        rollover_content = rollover.getElement('.rollover_info');
        if (rollover_content) {
          header_upper.setHTML(tar.innerHTML);
          rollover_content.setStyle('height', 'auto');
          height = rollover_content.getScrollSize().y;
          rt_height = rollover.getSize().y;
          rollover_content.setStyle('height', '0px');
          rh_height = rollover.getSize().y;

          // work out if this will hit the bottom
          dir = 0;
          if (row_index <= 3 && (pos.y+rt_height) > (window.getSize().y-30)) {
            dir = 1;
          }
          else if (row_index > 3) {
            dir = 1;
          }
          if (dir == 1 && (pos.y-rt_height+rh_height) < 200) {
            dir = 0;
          }

          dur = Math.ceil(height/100*250);
          if (dir) {
            fx2 = this.rollover_fx['el_'+details[1]];
            fx2.element.set('tween', {duration: dur});
            fx2.element.tween('top', [pos.y-rt_height+rh_height, pos.y]);
          }
          fx = this.rollover_fx[details[1]];
          fx.element.set('tween', {duration: dur});
          fx.element.tween('height', height);
        }
      }
    }
  },

  hideRollovers: function() {
    this.events.each(function(event) {
      rollover = this.getRollover(event[1]);
      if (rollover) {
        postfix = this.findPostfix(event[0]);
        event[0].removeClass('highlight_'+postfix);
        event[0].addClass('event_'+postfix);
        rollover.setStyle('display', 'none');
      }
    }.bind(this));
  },

  hideRollover: function(event_id) {
    // hide the rollover
    if (event_id) {
      rollover = this.getRollover(event_id);
      if (rollover) {
        rollover.setStyle('display', 'none');
      }
    }
  },

  addTableEvents: function() {
    this.event_calendar.addEvent('mouseleave', function() {
      this.hideRollovers();
    }.bind(this));
  },

  addCellEvents: function() {
    rows = this.event_calendar.rows;
    for (i = 0; i < rows.length; i++) {
      cells = this.event_calendar.rows[i].cells;
      for (j = 0; j < cells.length; j++) {
        cells[j].onmouseover = function() {
          this.hideRollovers();
        }.bind(this);
/*
        cells[j].addEvent('mouseover', function(e) {
          e = new Event(e).stop();
          this.hideRollovers();
        }.bind(this))
*/
      }
    }
  },

  addRolloverEvents: function() {
    this.rollover_fx = [];
    $ES('div', this.event_rollovers).each(function(el) {
      id = el.getAttribute('id');
      if (id ) {
        details = id.split("_");
        if (details && details[0] == 'eventinfo' &&
            el.parentNode == this.event_rollovers) {
          el.addEvent('mouseleave', function(e) {
            e = new Event(e).stop();
            tar = e.target;
            while (tar.tagName != 'DIV' || !tar.hasClass('event_rollover')) {
              tar = tar.parentNode;
            }
            details = tar.getAttribute('id').split("_");
            this.unHighlightEvents(details[1]);
            tar.setStyle('display', 'none');
          }.bind(this));
          rollover_content = el.getElement('.rollover_info');
          this.rollover_fx[details[1]] = new Fx.Tween(rollover_content, {wait:false});
          this.rollover_fx['el_'+details[1]] = new Fx.Tween(el, {wait:false});
        }
      }
    }.bind(this));
  },

  getRollover: function(event_id) {
    return $E('#eventinfo_'+event_id, this.event_rollovers);
  },
  getCell: function(day, month) {
    return $E('#day_'+parseInt(month, 10)+"_"+parseInt(day, 10), this.event_calendar);
  },

  getColumnWidths: function() {
    cells = this.event_calendar.rows[1].cells;
    for(i = 0; i < cells.length; i++) {
      this.cell_widths[i] = cells[i].offsetWidth;
    }
  },

  getEventWidth: function(day, month, duration) {
    width = 0;
    day_cell = this.getCell(day, month);
    max = day_cell.cellIndex + duration;
    if (max > this.cell_widths.length) {
      max = this.cell_widths.length;
    }
    for (i = day_cell.cellIndex; i < max; i++) {
      width += this.cell_widths[i];
    }
    return width-1;
  },

  toggleVisibility: function(type) {
    if (this.types_visible[type]) {
      this.types_visible[type] = 0;
    }
    else {
      this.types_visible[type] = 1;
    }
  },

  setVisibility: function() {
    for (var type in this.types_visible) {
      var style = 'visible';
      if (!this.types_visible[type]) {
        style = 'hidden';
      }
      $ES('.'+type, this.event_wrapper).each(function(el) {
        el.setStyle('visibility', style);
      }.bind(this));
    }
  },

  addKeyEvents: function() {
    event_types = $ES('p', this.calendar_key);
    event_types.each(function(type){
      type.addEvent('click', function(e) {
        e = new Event(e).stop();
        tar = e.target;
        while (tar.tagName != 'P') {
          tar = tar.parentNode;
        }
        tar_class = tar.className;
        this.toggleVisibility(tar_class);
        this.setVisibility();
        img = tar.getElement('img');
        if (this.types_visible[tar_class]) {
          tar.setStyle('color', '#000');
          img.setAttribute('src', base_url+'images/calendar/key_'+tar_class+'.gif');
        }
        else {
          tar.setStyle('color', '#AAA');
          img.setAttribute('src', base_url+'images/calendar/key_'+tar_class+'_off.gif');
        }
      }.bind(this));
    }.bind(this));

    this.key_fx = new Fx.Styles(this.calendar_key, {duration:200, wait:false});
    this.key_size = this.calendar_key.getSize();
    this.key_scroll_size = this.calendar_key.getScrollSize();
    // add action to toggle key open/closed
    $E('#toggle', this.calendar_key).addEvent('click', function(e) {
      curr_size = this.calendar_key.getSize();
      if (curr_size.y > this.key_size.y) {
        this.key_fx.start({'height':(this.key_size.y-18)+'px'});
      }
      else {
        this.key_fx.start({'height':(this.key_scroll_size.y)+'px'});
      }
    }.bind(this))
  },

  setVisible: function(str)
  {
    if (this.event_wrapper) {
      this.event_wrapper.setStyle('display', 'none');
      this.event_rollovers.setStyle('display', 'none');
    }

    this.event_wrapper = this.event_wrappers[str];
    this.event_rollovers = this.event_rolloversc[str];

    this.event_wrapper.setStyle('display', 'block');
    this.event_rollovers.setStyle('display', 'block');

    this.events = [];

    // parse events
    this.parseEvents();

    // position events
    this.positionEvents();

    // resize events
    this.resizeEvents();

    // set visiblity
    this.setVisibility();

    // add mouseleave events to rollovers
    this.addRolloverEvents();
  }

});
EventCalendar.implement(new Options);