var calObj = null;
var calObjFrame = null;
var dateField = null;
var monthStr = ['January','February','March','April','May','June','July','August','September','October','November','December'];

function isLeapYear(theYear) {
  return ((theYear % 4 == 0 && theYear % 100 != 0) || theYear % 400 == 0);
}

function generateCal(theDate,showNav,showTime) {
  if (!theDate || theDate == "") {
    theDate = new Date().toString();
  }
  var testDate;
  try {
    testDate = new Date(theDate);
    if (!testDate || isNaN(testDate)) {
      theDate = new Date().toString();
    }
  } catch(e) {
    theDate = new Date().toString();
  }
  var cDate = new Date(theDate);
  testDate = new Date('00/00/0000');
  if (cDate <= testDate) {
    cDate = new Date();
  }
  
  var daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];

  var calStr = "";
  var highlightToday = false;
  var highlightSelDay = false;
  var cMonth = cDate.getMonth();
  var cYear = cDate.getFullYear();
  var fDate = new Date(cYear,cMonth,1);
  var fDay = fDate.getDay();
  var today = new Date();
  var tYear = today.getFullYear();
  var tMonth = today.getMonth();
  var tDate = today.getDate();
  var sDate = new Date();

  if (dateField != null && dateField.value != "") {
    try {
      testDate = new Date('00/00/0000');
      sDate = new Date(dateField.value);
    } catch (e) {
      sDate = new Date();
    }
    if (sDate <= testDate) {
      sDate = new Date();
    }
  }
  var sYear = sDate.getFullYear();
  var sMonth = sDate.getMonth();
  var sDay = sDate.getDate();

  if (isLeapYear(cYear)) {
    daysInMonth[1] = 29;
  }
  if (cYear == tYear && cMonth == tMonth) {
    highlightToday = true;
  }
  if (cYear == sYear && cMonth == sMonth) {
    highlightSelDay = true;
  }
  if (showNav) {
    calStr += "<tr class=calMonthHead><td class=calNavButton>";
    calStr += "<a href=\"javascript:viewPreviousMonth('"+theDate+"',"+showTime+");\" title=\"View the previous month\">&lt;&lt;</a>";
    calStr += "</td><td colspan=5 class=calNav nowrap>"+getMonthList(cMonth)+" "+getYearList(cYear)+"</td><td class=calNavButton>";
    calStr += "<a href=\"javascript:viewNextMonth('"+theDate+"',"+showTime+");\" title=\"View the next month\">&gt;&gt;</a></td></tr>";
  } else {
    calStr += "<tr class=calMonthHead><td></td><td colspan=5>";
    calStr += monthStr[cMonth]+" "+cYear+"</td><td></td></tr>";
  }

  calStr += "<tr class=calHead><td>S</td><td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td></tr>";
  calStr += "<tr class=calRow>";
  for (var fr=0; fr<fDay; fr++) {
    calStr += "<td class=calBlankDay></td>";
  }
  var dayIndex = fDay;
  var curDate;
  for (var d=1; d<daysInMonth[cMonth]+1; d++) {
    curDate = (cMonth+1) + "/" + d + "/" + cYear;
    calStr += "<td ";
    if (highlightToday && d == tDate) {
      calStr += "class=calCurrentDay ";
    } else if (highlightSelDay && d == sDay) {
      calStr += "class=calCurSelDay ";
    } else {
      calStr += "class=calNormalDay ";
    }
    calStr += "onmouseover=\"hoverDay(this);\" ";
    calStr += "onmouseout=\"normalDay(this);\" ";
    calStr += "onclick=\"setDate('"+curDate;
    calStr += "');\">" + d + "</td>";
    if (++dayIndex == 7) {
      dayIndex = 0;
      calStr += "</tr><tr class=calRow>";
    }
  }
  if (dayIndex == 0) {
    calStr = calStr.substr(0,calStr.length-17);
  } else {
    for (var lr=dayIndex; lr<7; lr++) {
      calStr += "<td class=calBlankDay></td>";
    }
    calStr += "</tr>";
  }

  if (showTime) {
    calStr += "<tr><td colspan=7 class=calTime><b>Time:</b> ";
    calStr += getHourList('11:30 PM');
    calStr += "</td></tr>";
  }

  calStr += "<tr><td colspan=7 class=calLegend>";
  calStr += "<a href=\"javascript:closeCalWindow();\">Close Calendar [x]</a>";
  calStr += "</td></tr>";
  calStr = "<table class=calendarTable cellspacing=1>"+calStr+"</table>";

  return calStr;
}

function viewPreviousMonth(theDate,showTime) {
  theDate = new Date(theDate);
  var previousYear = theDate.getFullYear();
  var previousMonth = theDate.getMonth();
  if (previousMonth == 0) {
    previousMonth = 11;
    previousYear--;
  } else {
    previousMonth--;
  }
  if (calObj != null && calObjFrame != null) {
    calObj.innerHTML = generateCal((previousMonth+1)+"/1/"+previousYear,true,showTime);
    calObjFrame.style.width = calObj.clientWidth+"px";
    calObjFrame.style.height = calObj.clientHeight+"px";
  }
}

function viewNextMonth(theDate,showTime) {
  theDate = new Date(theDate);
  var nextYear = theDate.getFullYear();
  var nextMonth = theDate.getMonth();
  if (nextMonth == 11) {
    nextMonth = 0;
    nextYear++;
  } else {
    nextMonth++;
  }
  if (calObj != null && calObjFrame != null) {
    calObj.innerHTML = generateCal((nextMonth+1)+"/1/"+nextYear,true,showTime);
    calObjFrame.style.width = calObj.clientWidth+"px";
    calObjFrame.style.height = calObj.clientHeight+"px";
  }
}

function changeMonthYear() {
  var monthObj = document.getElementById("monthSel");
  var yearObj = document.getElementById("yearSel");
  var newDate = (parseInt(monthObj.options[monthObj.options.selectedIndex].value)+1) + "/1/" +
    yearObj.options[yearObj.options.selectedIndex].value;
  if (monthObj && yearObj) {
    if (calObj != null && calObjFrame != null) {
      calObj.innerHTML = generateCal(newDate,true,calObj.showTime);
      calObjFrame.style.width = calObj.clientWidth+"px";
      calObjFrame.style.height = calObj.clientHeight+"px";
    }
  }
}

function getMonthList(selMonth) {
  var moStr = "<select id=monthSel onchange=\"changeMonthYear();\">";
  for (var m=0; m<monthStr.length; m++) {
    moStr += "<option value=\""+m+"\"";
    if (m == selMonth) {
      moStr += " selected";
    }
    moStr += ">"+monthStr[m]+"</option>";
  }
  moStr += "</select>";
  return moStr;
}

function getYearList(selYear) {
  var yrStr = "<select id=yearSel onchange=\"changeMonthYear();\">";
  var curYear = new Date().getFullYear();
  for (var y=1901; y<curYear+10; y++) {
    yrStr += "<option value=\""+y+"\"";
    if (y == selYear) {
      yrStr += " selected";
    }
    yrStr += ">"+y+"</option>";
  }
  yrStr += "</select>";
  return yrStr;
}

function hoverDay(obj) {
  obj.style.cursor = 'hand';
  switch (obj.className) {
    case "calCurrentDay":
      obj.title = "This is today's date";
      break;
    case "calCurSelDay":
      obj.title = "This is the current date in the field linked to this calendar";
      break;
    case "calNormalDay":
    default:
      obj.title = "Click to automatically insert this date into the linked field";
      break;
  }
  obj.style.padding = '0px';
  obj.style.border = '2px solid red';
}

function normalDay(obj) {
  obj.style.border = 'none';
  obj.style.padding = '2px';
}

function setDate(theDate) {
  if (calObj && calObjFrame) {
    if (calObj.showTime) {
      var timeObj = getCalElement("timeField","input");
      if (timeObj) {
        theDate += " "+timeObj.value;
      }
    }
    if (dateField != null && theDate != "") {
      if (theDate.indexOf(" ") == -1) {
        var dateParts = theDate.split("/");
        if (dateParts.length == 3) {
          theDate = (dateParts[0].length == 1 ? "0"+dateParts[0]:dateParts[0]) +
            "/" + (dateParts[1].length == 1 ? "0"+dateParts[1]:dateParts[1]) +
            "/" + dateParts[2];
        }
      }
      dateField.value = theDate;
      dateField.changed = true;
      if (dateField.createTextRange) {
        var tr = dateField.createTextRange();
        if (tr) {
          tr.moveStart('character',theDate.length);
          tr.collapse();
          tr.select();
        }
      } else {
        dateField.focus();
      }
      if (g_dateCascade) {
        eval(g_dateCascade);
      }
    }
    calObj.timeChanged = false;
    closeCalWindow();
  }
}

function getCalElement(elName,tagName) {
  var els = tagName ? document.getElementsByTagName(tagName):
    document.getElementsByTagName("*");
  var el = null;
  for (var i=0; i<els.length; i++) {
    if ((el = els[i]) && el.id && 
      el.id.indexOf(elName) != -1) {
        break;
    }
  }
  return el;
}

function renderCal(dateFieldId,showTime) {
  var calIcon = getCalElement('cal_'+dateFieldId,"img");
  var dateStr = new Date().toString();
  dateField = getCalElement(dateFieldId,"input");
  if (dateField != null && dateField.value != "") {
    dateStr = dateField.value;
  }
  if (calObj != null) {
    document.body.removeChild(calObj);
    calObj = null;
  }
  if (calObjFrame != null) {
    document.body.removeChild(calObjFrame);
    calObjFrame = null;
  }
  calObj = document.createElement("div");
  calObjFrame = document.createElement("iframe");
  calObjFrame.style.position = 'absolute';
  calObjFrame.style.display = 'none';
  calObjFrame.src = null;
  document.body.appendChild(calObjFrame);
  calObj.innerHTML = generateCal(dateStr,true,showTime);
  calObj.showTime = showTime;
  calObj.style.position = 'absolute';
  calObj.style.display = 'block';
  document.body.appendChild(calObj);
  var xPos = getLeftPos(calIcon);
  var yPos = getTopPos(calIcon);
  if (xPos + calObj.clientWidth > document.body.clientWidth + document.body.scrollLeft) {
    xPos = document.body.clientWidth - calObj.clientWidth + document.body.scrollLeft;
  }
  var bodyHeight = window.innerHeight;
  if (document.all) {
    bodyHeight = document.body.clientHeight;
  }
  if (yPos + calObj.clientHeight > bodyHeight + document.body.scrollTop) {
    yPos = bodyHeight - calObj.clientHeight + document.body.scrollTop;
  }
  calObj.style.left = xPos+"px";
  calObj.style.top = yPos+"px";
  calObjFrame.style.width = calObj.clientWidth+"px";
  calObjFrame.style.height = calObj.clientHeight+"px";
  calObjFrame.style.top = yPos+"px";
  calObjFrame.style.left = xPos+"px";
  if (document.all) {
    calObjFrame.style.display = 'block';
  }
}

function closeCalWindow() {
  if (calObj && calObjFrame) {
    if (calObj.timeChanged) {
      if (dateField) {
        var timeObj = getCalElement("timeField","input");
        if (timeObj) {
          var parts = dateField.value.split(' ');
          if (parts.length > 1 && parts[0] != "") {
            dateField.value = parts[0] + " " +
            timeObj.value;
          }
        }
      }
    }
    calObj.style.display='none';
    calObj.timeChanged = false;
    calObj.showTime = false;
    calObjFrame.style.display='none';
  }
}

function generateHoursArray() {
  var hrs = new Array();
  for (var h=0; h<48; h++) {
    hrs[h] = (parseInt(h/2)%12==0?'12':parseInt(h/2)%12)+":"+
      (h%2==0?'00':'30')+" "+(h/23>1?'PM':'AM');
  }
  return hrs;
}

function getTimeStr(current) {
  var timeObj = null;
  if (current) {
    timeObj = new Date();
  } else {
    if (dateField) {
      timeObj = new Date(dateField.value);
    }
  }
  var hour = timeObj.getHours();
  if (isNaN(hour)) {
    hour = 12;
  }
  var minutes = timeObj.getMinutes();
  if (isNaN(minutes)) {
    minutes = 0;
  }
  return (hour%12==0?'12':hour%12)+":"+(minutes<10?'0'+minutes:minutes)+" "+(hour>11?'PM':'AM');
}

function getHourList() {
  var hoursArray = generateHoursArray();
  var hrStr = "<select id=hourSel onchange=\"changeHour(this,'timeField');\">";
  var selectedItem = "";
  if (dateField) {
    if (dateField.value == "") {
      hrStr += "<option value=\"\" selected>Select</option>";
    } else {
      selectedItem = getTimeStr(false);
    }
  }
  var listTime = null;
  var selTime = null;
  for (var h=0; h<48; h++) {
    hrStr += "<option value=\""+hoursArray[h]+"\"";
    listTime = new Date("01/01/2000 "+hoursArray[(h+1)>47?0:(h+1)]);
    selTime = new Date("01/01/2000 "+selectedItem);
    if (listTime > selTime  && hrStr.indexOf("selected") == -1) {
      hrStr += " selected";
    }
    hrStr += ">"+hoursArray[h]+"</option>";
  }
  hrStr += "</select>&nbsp;<input class=calTimeField id=timeField type=text size=8 maxlength=8 value=\"";
  if (dateField) {
    if (dateField.value == "") {
      hrStr += getTimeStr(true);
    } else {
      hrStr += getTimeStr(false);
    }
  }
  hrStr += "\" onchange=\"setTimeChanged(true);\">";
  return hrStr;
}

function changeHour(selObj,timeName) {
  if (selObj && timeName && calObj) {
    var timeObj = getCalElement(timeName,"input");
    if (timeObj) {
      timeObj.value = selObj.options[selObj.options.selectedIndex].value;
      calObj.timeChanged = true;
    }
  }
}

function setTimeChanged(mode) {
  if (calObj) {
    calObj.timeChanged = mode;
  }
}
