var CourseCalendarPrototype = Class.create({
  initialize: function(element, options) {
    this.element = $(element);
    this.options = $H(options);
    this.calendars = $A();
    
    this.weekdayNames = Locale.get('dayNames');
    this.monthNames   = Locale.get('monthNames');
    this.format       = this.options.get('format')     || Locale.get('format');
    this.weekOffset   = this.options.get('weekOffset') || Locale.get('weekOffset');
    
    this.options = $H({ months: 1 }).merge(options || {});;
    this.months = this.options.get('months');
    
    this.dates = this.dates.collect(function(ds) { return Date.parseToObject(ds) })
    this.date = Date.parse(this.dates.first().clone());
    
    this.element.insert(new Element('div', { id: this.element.id + '_container' }));
    this.months.times(function(month) { this.createCalendar(month) }.bind(this));
    this.populate();
  },
  createCalendar: function() {
    var calendar = new Element('table', {
      id: this.element.id + '_calendar_' + this.calendars.length, border: 0, cellspacing: 0, cellpadding: 5
    });
    calendar.insert(new Element('caption'));

    var head = new Element('thead');
    var row  = new Element('tr');
    this.weekdayNames.length.times(function(column) {
      var weekday = this.weekdayNames[(column + this.weekOffset) % 7];
      var cell = new Element('th', { scope: 'col', abbr: weekday }).update(weekday.substring(0,1));
      row.insert(cell);
    }.bind(this));
    head.insert(row);
    calendar.insert(head);

    var body = new Element('tbody');
    (6).times(function(rowNumber) {
      var row = new Element('tr');
      this.weekdayNames.length.times(function(column) {
        var cell = new Element('td');
        row.insert(cell);
      });
      body.insert(row);
    }.bind(this));
    calendar.insert(body);
    
    this.element.down('div#' + this.element.id + '_container').insert(calendar);
    this.calendars.push(calendar);
    this.months = this.calendars.length;
    return this;
  },
  
  populate: function() {
    var month = this.date.neutral();
    month.setDate(1);
    this.calendars.each(function(calendar) {
      var caption = calendar.select('caption').first();
      caption.update(this.monthNames[month.getMonth()] + ' ' + month.getFullYear());

      var iterator = new Date(month);
      var offset = (iterator.getDay() - this.weekOffset) % 7;
      var inactive = offset > 0 ? 'pre beyond' : false;
      iterator.setDate(iterator.getDate() - offset);
      if (iterator.getDate() > 1 && !inactive) {
        iterator.setDate(iterator.getDate() - 7);
        if (iterator.getDate() > 1) inactive = 'pre beyond';
      }
      calendar.select('td').each(function(day) {
        day.date = new Date(iterator); // Is this expensive (we unload these later)? We could store the epoch time instead.
        day.update(day.date.getDate()).writeAttribute('class', inactive || 'active');
        if ((this.earliest && day.date < this.earliest) || (this.latest && day.date > this.latest))
          day.addClassName('unselectable');
        else
          day.addClassName('selectable');
        
        if (this.dates.any(function(d) { return Date.equals(day.date, d)  }))
          day.addClassName('selected');
          
        this.extra(day);
          
        iterator.setDate(iterator.getDate() + 1);
        if (iterator.getDate() == 1) inactive = inactive ? false : 'post beyond';
      }.bind(this));
      
      month.setMonth(month.getMonth() + 1);
    }.bind(this));
    return this;
  },
  
  extra: function(day) {
    return true;
  }
});

var CourseSectionCalendar = Class.create(CourseCalendarPrototype, {
  initialize: function($super, element, options, dates, facility_parts, length) {
    this.dates = dates;
    this.facility_parts = facility_parts;
    this.running_iii = 0;
    this.length = length;
    
    $super(element, options);
  },
  
  extra: function(day) {
    var the_parts = this.facility_parts[day.date.toString("yyyy-MM-dd")] || [];
    if (this.length <= 0 || the_parts.length <= 0) {
      return false;
    }
    
    day.div = $(document.createElement('div'));
    day.div.addClassName("details");
    the_parts.each(function(part) {
      var div = $(document.createElement('div'));
      if (this.length > 1) {
        div.innerHTML = "<div class=\"event"+part.ident+"\" style=\"margin-top:0.6em;float:left;width; 14px; height: 14px; border: solid 1px #aaa\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>&nbsp;&nbsp;<b>" + part.name + "</b>";
        div.appendChild(document.createElement('br'));
        day.addClassName("event" + part.ident);
      }
      div.appendChild(document.createTextNode(' ' + part.start_time + " to " + part.end_time));
      div.appendChild(document.createElement('br'));
      div.appendChild(document.createTextNode(' ' + part.site));
      div.appendChild(document.createElement('br'));
      if (part.room && part.room.length > 0) {
         div.appendChild(document.createTextNode(part.room));
      }
      day.div.appendChild(div);
    }.bind(this));
    
    new Event.observe(day, 'mouseover', this.mouseover.bind(this));
    new Event.observe(day, 'mouseout', this.mouseout.bind(this));
    
    this.build_listeners(day);
    
    day.div.hide();
    day.appendChild(day.div);
  },
  
  build_listeners: function(day) {
    return true;
  },
  
  mouseover: function(event) {
    var element = event.element();
    var div = element.down('div.details');
    if (div) {
      div.style.top = element.positionedOffset().last() + 24 + 'px';
      div.style.left = element.positionedOffset().first() - element.cumulativeScrollOffset().first() + element.getWidth() + 'px';
      div.show();
    }
  },
  
  mouseout: function(event) {
    var element = event.element();
    var div = element.down('div.details');
    if (div)
      div.hide();
  }
});

var CourseCalendar = Class.create(CourseSectionCalendar, {
  build_listeners: function(day) {
  }
});