var Calendar = function (pCalendarTable, pEventTable, pEvents, pDateIndexes) {

  this.calendarTable = pCalendarTable;
  this.eventTable = pEventTable;
  this.events = pEvents;
  this.dateIndexes = pDateIndexes;

  this.dates = new Array();
  for (var date in this.dateIndexes) {
    this.dates.push(date);
  }

  if (this.dates.length == 0) {
    var date = new Date();
    this.minDate = date;
    this.maxDate = date;
  }
  else {
    var date = this.dates[0];
    this.minDate = new Date(date.substr(0, 4), date.substr(5, 2) - 1, date.substr(8, 2));
    var date = this.dates[this.dates.length - 1];
    this.maxDate = new Date(date.substr(0, 4), date.substr(5, 2) - 1, date.substr(8, 2));
  }

  this.timer = null;

  var tempThis = this;
  this.eventTable.onmouseover = function () {
    tempThis.showEvents();
  };
  this.eventTable.onmouseout = function () {
    tempThis.preHideEvents();
  };

  var date = new Date();
  this.buildCalendarTable(date.getMonth(), date.getFullYear());

}

Calendar.prototype.months = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

Calendar.prototype.days = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");

Calendar.prototype.buildEventTable = function (pFullDate) {
  var doc = this.eventTable.ownerDocument || this.eventTable.document;
  tableHead = this.eventTable.createTHead();
  while (tableHead.rows.length > 0) {
    tableHead.deleteRow(-1);
  }
  var row = tableHead.insertRow(-1);
  var cell = row.insertCell(-1);
  cell.innerHTML = "Dates";
  var cell = row.insertCell(-1);
  cell.innerHTML = "Service";
  var cell = row.insertCell(-1);
  cell.innerHTML = "Client / Location";
  if (this.eventTable.tBodies.length == 0) {
    var tableBody = doc.createElement("tbody");
    this.eventTable.appendChild(tableBody);
  }
  var tableBody = this.eventTable.tBodies[0];
  while (tableBody.rows.length > 0) {
    tableBody.deleteRow(-1);
  }
  var indexes = this.dateIndexes[pFullDate];
  for (var i = 0; i < indexes.length; i++) {
    var event = this.events[indexes[i]];
    var row = tableBody.insertRow(-1);
    var cell = row.insertCell(-1);
    cell.innerHTML = event[1];
    var cell = row.insertCell(-1);
    if (event[0] == "T") {
      cell.innerHTML = "<a href='part.php?sub=training&amp;alias=" + event[4] + "'>" + event[2] + "</a>";
    }
    else {
      cell.innerHTML = event[2];
    }
    var cell = row.insertCell(-1);
    cell.innerHTML = event[3];
  }
}

Calendar.prototype.showEvents = function (pCell) {
  clearTimeout(this.timer);
  if (pCell) {
    this.buildEventTable(pCell.date);
    this.eventTable.style.left = utilGetAbsoluteLeft(this.calendarTable) - (this.eventTable.offsetWidth - this.calendarTable.offsetWidth) / 2 + "px";
    this.eventTable.style.top = utilGetAbsoluteTop(pCell) + pCell.offsetHeight + "px";
    this.eventTable.style.visibility = "visible";
  }
}

Calendar.prototype.preHideEvents = function (pCell) {
  var tempThis = this;
  this.timer = setTimeout(function () {
    tempThis.hideEvents();
  }, 300);
}

Calendar.prototype.hideEvents = function () {
  this.eventTable.style.left = "-1000px";
  this.eventTable.style.top = "-1000px";
  this.eventTable.style.visibility = "hidden";
}

Calendar.prototype.buildCalendarTable = function (pMonth, pYear) {

  var doc = this.calendarTable.ownerDocument || this.calendarTable.document;

  var milliSecondsInADay = 1000 * 60 * 60 * 24;
  var currMonthDate = new Date(pYear, pMonth, 1);
  var prevMonthDate = new Date(currMonthDate.getTime() - milliSecondsInADay);
  var nextMonthDate = new Date(currMonthDate.getTime() + 31 * milliSecondsInADay);
  nextMonthDate.setDate(1);

  if (this.calendarTable.tBodies.length == 0) {
    var tableBody = doc.createElement("tbody");
    this.calendarTable.appendChild(tableBody);
  }
  var tableBody = this.calendarTable.tBodies[0];
  while (tableBody.rows.length > 0) {
    tableBody.deleteRow(-1);
  }

  var tempThis = this;

  var row = tableBody.insertRow(-1);
  var cell = row.insertCell(-1);
  if (this.minDate <= prevMonthDate) {
    cell.className = "calendar-prev";
    cell.onclick = function () {
      tempThis.buildCalendarTable(prevMonthDate.getMonth(), prevMonthDate.getFullYear());
    };
    cell.onmouseout = function () {
      removeClassName(this, "calendar-prev-hover");
    };
    cell.onmouseover = function () {
      addClassName(this, "calendar-prev-hover");
    };
    cell.innerHTML = "&lt;";
  }
  else {
    cell.innerHTML = "&nbsp;";
  }
  var cell = row.insertCell(-1);
  cell.className = "calendar-month";
  cell.colSpan = 5;
  cell.innerHTML = this.months[pMonth] + " " + pYear;
  var cell = row.insertCell(-1);
  if (this.maxDate >= nextMonthDate) {
    cell.className = "calendar-next";
    cell.onclick = function () {
      tempThis.buildCalendarTable(nextMonthDate.getMonth(), nextMonthDate.getFullYear());
    };
    cell.onmouseout = function () {
      removeClassName(this, "calendar-next-hover");
    };
    cell.onmouseover = function () {
      addClassName(this, "calendar-next-hover");
    };
    cell.innerHTML = "&gt;";
  }
  else {
    cell.innerHTML = "&nbsp;";
  }

  var row = tableBody.insertRow(-1);
  row.className = "calendar-days";
  for (var day = 0; day < 7; day++) {
    var cell = row.insertCell(-1);
    cell.innerHTML = this.days[day].substr(0, 3);
  }

  var row = tableBody.insertRow(-1);
  row.className = "calendar-dates";
  var day = currMonthDate.getDay();
  if (day > 0) {
    var cell = row.insertCell(-1);
    cell.colSpan = day;
    cell.innerHTML = "&nbsp;";
  }
  var lastDateOfMonth = (new Date(nextMonthDate.getTime() - milliSecondsInADay)).getDate();
  var fullDatePrefix = pYear + "-" + utilZeroPad(pMonth + 1, 2) + "-";
  for (var date = 1; date <= lastDateOfMonth; date++, day++) {
    if (day == 7) {
      day = 0;
      row = tableBody.insertRow(-1);
      row.className = "calendar-dates";
    }
    var fullDate = fullDatePrefix + utilZeroPad(date, 2);
    var cell = row.insertCell(-1);
    if (findInArray(this.dates, fullDate) != -1) {
      cell.className = "calendar-event-date";
      cell.date = fullDate;
      cell.onmouseout = function () {
        tempThis.preHideEvents(this);
      };
      cell.onmouseover = function () {
        tempThis.showEvents(this);
      };
    }
    cell.innerHTML = date;
  }
  if (day < 7) {
    var cell = row.insertCell(-1);
    cell.colSpan = 7 - day;
    cell.innerHTML = "&nbsp;";
  }

}

