var months = new Array("jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec");
var c_arrMonthNames = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
var c_arrMonthDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
var c_arrWeekNames = new Array('firstweek', 'secondweek', 'thirdweek', 'fourthweek', 'fifthweek', 'sixthweek');
var c_arrWeekNamesAbrv = new Array('fsw', 'sdw', 'tdw', 'frw', 'ftw', 'sxw');
var c_arrDataHolidays = new Array();
var c_arrBankHolidays = new Array();
var c_arrpedt = new Array();
var c_arrchkdt = new Array();
var curyear = 0;
var pedt = new Date(); //pay end date in milliseconds
var datediff = 0; //difference between pay end date and check date in days
var ie4 = false;


function getposOffset2(what, offsettype) {
  var totaloffset = (offsettype == "left") ? what.offsetLeft : what.offsetTop;
  var parentEl = what.offsetParent;
  while (parentEl != null) {
    totaloffset = (offsettype == "left") ? totaloffset + parentEl.offsetLeft : totaloffset + parentEl.offsetTop;
    parentEl = parentEl.offsetParent;
  }
  return totaloffset;
}

function clearbrowseredge2(obj, whichedge, dropmenuobj) {
  var edgeoffset = 0
  if (whichedge == "rightedge") {
    var windowedge = ie4 && !window.opera ? iecompattest().scrollLeft + iecompattest().clientWidth - 15 : window.pageXOffset + window.innerWidth - 15
    dropmenuobj.contentmeasure = dropmenuobj.offsetWidth
    if (windowedge - dropmenuobj.x < dropmenuobj.contentmeasure)
      edgeoffset = dropmenuobj.contentmeasure - obj.offsetWidth
  } else {
    var topedge = ie4 && !window.opera ? iecompattest().scrollTop : window.pageYOffset
    var windowedge = ie4 && !window.opera ? iecompattest().scrollTop + iecompattest().clientHeight - 15 : window.pageYOffset + window.innerHeight - 18
    dropmenuobj.contentmeasure = dropmenuobj.offsetHeight
    if (windowedge - dropmenuobj.y < dropmenuobj.contentmeasure) {
      edgeoffset = dropmenuobj.contentmeasure + obj.offsetHeight
      if ((dropmenuobj.y - topedge) < dropmenuobj.contentmeasure)
        edgeoffset = dropmenuobj.y + obj.offsetHeight - topedge
    }
  }
  return edgeoffset
}

/* THE FOLLOWING CODE IS REQUIRED FOR THE CALENDAR TO WORK */

var m_elemCalendar = null;
var m_elemTarget = null;
var m_elemFrame = null;
var m_elemContainer = null;
var m_ownerDocument = null;

function calShowCalendarFrame(elemCalendar, elemTarget, elemContainer, elemFrame, ownerDocument, frameTarget) {
  if (elemTarget.disabled || elemTarget.readOnly) {
    return;
  }

  elemFrame.x = getposOffset2(elemCalendar, "left");
  elemFrame.y = getposOffset2(elemCalendar, "top");
  elemFrame.style.left = elemFrame.x - clearbrowseredge2(elemCalendar, "rightedge", elemFrame) + 2 + "px";
  elemFrame.style.top = elemFrame.y - clearbrowseredge2(elemCalendar, "bottomedge", elemFrame) + (elemCalendar.offsetHeight + 2) + "px";

  if (elemContainer.calWidth != null) {
    elemFrame.style.width = elemContainer.calWidth;
  }
  if (elemContainer.calHeight != null) {
    elemFrame.style.height = elemContainer.calHeight;
  }

  m_elemCalendar = elemCalendar;
  m_elemTarget = elemTarget;
  m_elemFrame = elemFrame;
  m_elemContainer = elemContainer;
  m_ownerDocument = ownerDocument;

  elemFrame.src = frameTarget;
}

/* END CALENDAR CODE */

function InitializeLeapYear(m_nYear) {
  var leapYear = false;
  if ((m_nYear % 4) == 0) {
    if (((m_nYear % 100) != 0) || ((m_nYear % 400) == 0)) {
      leapYear = true;
    }
  }

  if (leapYear == true) { c_arrMonthDays[1] = 29; } else { c_arrMonthDays[1] = 28; }
}

function fix2digityear(millidate) {
  var tmpmillidate = new Date();
  var tmpyear = 0;
  tmpmillidate.setTime(millidate);
  tmpyear = tmpmillidate.getFullYear();
  if (tmpyear < 1940) {
    tmpmillidate.setFullYear((tmpyear + 100));
    return tmpmillidate.getTime();
  }
  return millidate;
}

function show_working() {
  document.getElementById('working').style.visibility = 'visible';
}

function hide_working() {
  document.getElementById('working').style.visibility = 'hidden';
}


function updateCal() {
  document.getElementById("calendar").innerHTML = "Generating Calendars";
  createCookie("freq", document.getElementById("optfreq").value, 365);
  createCookie("pedt", document.getElementById("txtpedt").value, 365);
  createCookie("chkdt", document.getElementById("txtchkdt").value, 365);
  isachkdt__startpos = 0;
  isapedt__startpos = 0;
  isadscholiday__startpos = 0;
  isabankholiday__startpos = 0;

  var freq = document.getElementById("optfreq").value;
  pedt = fix2digityear(Date.parse(document.getElementById("txtpedt").value));
  var pedt2 = fix2digityear(Date.parse(document.getElementById("txtpedt2").value));
  document.getElementById("txtpedtval").style.display = isNaN(pedt) ? "inline" : "none";
  document.getElementById("txtpedtval2").style.display = isNaN(pedt2) ? "inline" : "none";
  var chkdt = fix2digityear(Date.parse(document.getElementById("txtchkdt").value));
  var chkdt2 = fix2digityear(Date.parse(document.getElementById("txtchkdt2").value));
  document.getElementById("txtchkdtval").style.display = isNaN(chkdt) ? "inline" : "none";
  document.getElementById("txtchkdtval2").style.display = isNaN(chkdt2) ? "inline" : "none";
  InitializeLeapYear(curyear);
  setupHolidays(curyear);
  if (!isNaN(chkdt) && !isNaN(pedt) && freq != "" && (freq != "semimonthly" || (!isNaN(chkdt2) && !isNaN(pedt2)))) 
    rollpedt(freq, pedt, pedt2, chkdt, chkdt2);
  LoadCalendarYear(freq);
  hide_working();
}

function rollpedt(freq, ped1, ped2, cd1, cd2) {
  c_arrpedt = new Array();
  c_arrchkdt = new Array();
  addToArr(c_arrpedt, freq, ped1, false); 
  addToArr(c_arrchkdt, freq, cd1, true);
  if(freq == "semimonthly"){
    addToArr(c_arrpedt, freq, ped2, false); 
    addToArr(c_arrchkdt, freq, cd2, true);  
    c_arrpedt.sort();
    c_arrchkdt.sort();
  }
}

function WkendHldyAdj(xfreq, dte) {
  var freq = xfreq;
  var toReturn = dte;
  for(; (((freq=="semimonthly" || freq=="monthly") && 
              (getdowfrommilli(toReturn) == 0 || 
              getdowfrommilli(toReturn) == 6)
           ) || IsHoliday(toReturn)); toReturn -= daymilli, freq = "monthly");
  return toReturn;
}

function BiWeeklyVal(dte){
  return ((dte/daymilli)%14)<7?1:2;
}

function AddMonth(dte){
  var day = getdayfrommilli(dte);
  var mo = getmofrommilli(dte);
  var nxtmo = (mo + 1) % 12;
  return dte + (day<=c_arrMonthDays[nxtmo] ? c_arrMonthDays[mo] : (c_arrMonthDays[nxtmo] + c_arrMonthDays[mo] - day) )*daymilli;
}

function addToArr(arr, freq, dte, adjust) {
  if (c_arrMonthDays[getmofrommilli(dte)] == getdayfrommilli(dte)) dte = Date.parse("1/31/" + curyear);
  arr.push(dte);
  var tmpnextyear = Date.parse("1/1/" + (curyear + 1));  
  var lastDt = dte;
  for(var limit = 0; limit<100 && lastDt<tmpnextyear; ++limit){
    lastDt += 3 * daymilli
    lastDt = getNextDate(lastDt, freq, dte, adjust);
    arr.push(lastDt);
  }
}

var daymilli = 24 * 60 * 60 * 1000;
function getNextDate(DateAfter, freq, dte, adjust){
  var toReturn = DateAfter;
  if(freq == "weekly" || freq == "biweekly"){
    var DOW = getdowfrommilli(dte);
    var DayDiff = DOW - getdowfrommilli(toReturn);
    if(DayDiff<0) DayDiff += 7;
    toReturn += DayDiff * daymilli;
    if(freq == "biweekly" && BiWeeklyVal(toReturn) != BiWeeklyVal(dte)) toReturn += 7 * daymilli;
  }else {
    var pcDOM = getdayfrommilli(dte);
    var TargetDay = c_arrMonthDays[getmofrommilli(DateAfter)];
    if(pcDOM < TargetDay) TargetDay = pcDOM;
    if(TargetDay<=0) TargetDay = 1;
    toReturn = Date.parse("" + (getmofrommilli(DateAfter)+1) + "/" + TargetDay + "/" + getyearfrommilli(DateAfter));
    if(TargetDay<=getdayfrommilli(DateAfter)) toReturn = AddMonth(toReturn);
  }
  if(adjust) 
    toReturn = WkendHldyAdj(freq, toReturn);
  if(toReturn <= DateAfter)
    return getNextDate(DateAfter + 3 * daymilli, freq, dte, adjust);
  return toReturn;
}

var isapedt__startpos = 0;
function isapedt(curday) {
  var i;
  for (i = isapedt__startpos; i < c_arrpedt.length; ++i) {
    if (parseInt(c_arrpedt[i]/daymilli) == parseInt(curday.getTime()/daymilli)) {
      isapedt__startpos = i + 1;
      return true;
    }
  }
  return false;
}

var isachkdt__startpos = 0;
function isachkdt(curday) {
  var i;
  for (i = isachkdt__startpos; i < c_arrchkdt.length; ++i) {
    if (parseInt(c_arrchkdt[i] / daymilli) == parseInt(curday.getTime() / daymilli)) {
      isachkdt__startpos = i + 1;
      return true;
    }
  }
  return false;
}

//xdate is date in milli
function getmofrommilli(xdate) {
  var tmpDate = new Date();
  tmpDate.setTime(xdate);
  return tmpDate.getMonth();
}

//xdate is date in milli
function getdayfrommilli(xdate) {
  var tmpDate = new Date();
  tmpDate.setTime(xdate);
  return tmpDate.getDate();
}

function getdowfrommilli(xdate) {
  var tmpDate = new Date();
  tmpDate.setTime(xdate);
  return tmpDate.getDay();
}

function getyearfrommilli(xdate) {
  var tmpDate = new Date();
  tmpDate.setTime(xdate);
  return tmpDate.getFullYear();
}

function createCookie(name, value, days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    var expires = "; expires=" + date.toGMTString();
  }
  else var expires = "";
  document.cookie = name + "=" + value + expires + "; path=/";
}

function readCookie(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for (var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') c = c.substring(1, c.length);
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
  }
  return null;
}

function eraseCookie(name) {
  createCookie(name, "", -1);
}

function doCookieStuff() {
  if (readCookie("freq"))
    document.getElementById("optfreq").value = readCookie("freq");
  if (readCookie("pedt"))
    document.getElementById("txtpedt").value = readCookie("pedt");
  if (readCookie("chkdt"))
    document.getElementById("txtchkdt").value = readCookie("chkdt");
}

function semiChange() {
  if (jQuery('#optfreq').val() == "semimonthly") {
    jQuery('#calsettings').addClass('semi');
    jQuery('#pcapt').text('First pay end date:');
    jQuery('#ccapt').text('First check date:');
  } else {
    jQuery('#calsettings').removeClass('semi');
    jQuery('#pcapt').text('Pay end date:');
    jQuery('#ccapt').text('Check date:');
  }
}

function LoadCalendar() {
  jQuery('#optfreq').change(semiChange).change();
  jQuery("input[type='text']").datepicker();
  doCookieStuff();
  curyear = (new Date()).getYear();
  if (curyear < 2000) { curyear = curyear + 1900; }
  updateCal();
  semiChange();
}

function prevYear() {
  --curyear;
  updateCal();
}

function nextYear() {
  ++curyear;
  updateCal();
}

var isadscholiday__startpos = 0;
function DSCHoliday(curDay, quickver) {
  var i;
  for (i = (quickver ? isadscholiday__startpos : 0); i < c_arrDataHolidays.length; i += 3) {
    if (c_arrDataHolidays[i + 1] == curDay.getMonth() && c_arrDataHolidays[i + 2] == curDay.getDate()) {
      holidayname = c_arrDataHolidays[i]
      if (quickver)
        isadscholiday__startpos = i + 3;
      return true;
    }
  }
  return false;
}

var holidayname = "";
var isabankholiday__startpos = 0;
function BankHoliday(curDay, quickver) {
  var i;
  for (i = (quickver ? isabankholiday__startpos : 0); i < c_arrBankHolidays.length; i += 3) {
    if (c_arrBankHolidays[i + 1] == curDay.getMonth() && c_arrBankHolidays[i + 2] == curDay.getDate()) {
      holidayname = c_arrBankHolidays[i]
      if (quickver)
        isabankholiday__startpos = i + 3;
      return true;
    }
  }
  return false;
}

function setupHolidays(year) {
  var tmpDate = new Date();
  c_arrDataHolidays = new Array();
  c_arrBankHolidays = new Array();

  tmpDate.setFullYear(year, 0, 1);
  c_arrBankHolidays[c_arrBankHolidays.length] = "Martin Luther King, Jr. Day";
  c_arrBankHolidays[c_arrBankHolidays.length] = 0;
  c_arrBankHolidays[c_arrBankHolidays.length] = ((16 - tmpDate.getDay()) < 15) ? (16 - tmpDate.getDay()) + 7 : (16 - tmpDate.getDay()); //third monday in jan
  tmpDate.setFullYear(year, 1, 1);
  c_arrBankHolidays[c_arrBankHolidays.length] = "President's Day";
  c_arrBankHolidays[c_arrBankHolidays.length] = 1;
  c_arrBankHolidays[c_arrBankHolidays.length] = ((16 - tmpDate.getDay()) < 15) ? (16 - tmpDate.getDay()) + 7 : (16 - tmpDate.getDay()); //third monday in feb
  tmpDate.setFullYear(year, 9, 1);
  c_arrBankHolidays[c_arrBankHolidays.length] = "Columbus Day";
  c_arrBankHolidays[c_arrBankHolidays.length] = 9;
  c_arrBankHolidays[c_arrBankHolidays.length] = ((9 - tmpDate.getDay()) < 8) ? (9 - tmpDate.getDay()) + 7 : (9 - tmpDate.getDay()); //second monday in oct
  tmpDate.setFullYear(year, 10, 11);
  c_arrBankHolidays[c_arrBankHolidays.length] = "Veteran's Day";
  c_arrBankHolidays[c_arrBankHolidays.length] = 10;
  c_arrBankHolidays[c_arrBankHolidays.length] = (tmpDate.getDay() == 0) ? 12 : (tmpDate.getDay() == 6) ? 10 : 11; //nov 11 or nearest wkdy

  tmpDate.setFullYear(year, 0, 1);
  if (tmpDate.getDay() != 6) {
    c_arrDataHolidays[c_arrDataHolidays.length] = "New Years";
    c_arrDataHolidays[c_arrDataHolidays.length] = 0;
    c_arrDataHolidays[c_arrDataHolidays.length] = (tmpDate.getDay() == 0) ? 2 : 1;
  }
  tmpDate.setFullYear(year, 4, 31);
  c_arrDataHolidays[c_arrDataHolidays.length] = "Memorial Day";
  c_arrDataHolidays[c_arrDataHolidays.length] = 4;
  c_arrDataHolidays[c_arrDataHolidays.length] = (tmpDate.getDay() != 0) ? 31 - (tmpDate.getDay() - 1) : 25; //last mon in may
  tmpDate.setFullYear(year, 6, 4);
  c_arrDataHolidays[c_arrDataHolidays.length] = "Independence Day";
  c_arrDataHolidays[c_arrDataHolidays.length] = 6;
  c_arrDataHolidays[c_arrDataHolidays.length] = (tmpDate.getDay() == 0) ? 5 : (tmpDate.getDay() == 6) ? 3 : 4;
  tmpDate.setFullYear(year, 8, 1);
  c_arrDataHolidays[c_arrDataHolidays.length] = "Labor Day";
  c_arrDataHolidays[c_arrDataHolidays.length] = 8;
  c_arrDataHolidays[c_arrDataHolidays.length] = ((2 - tmpDate.getDay()) < 1) ? (2 - tmpDate.getDay()) + 7 : (2 - tmpDate.getDay()); //first monday in sep
  tmpDate.setFullYear(year, 10, 1);
  c_arrDataHolidays[c_arrDataHolidays.length] = "Thanksgiving";
  c_arrDataHolidays[c_arrDataHolidays.length] = 10;
  c_arrDataHolidays[c_arrDataHolidays.length] = ((26 - tmpDate.getDay()) < 22) ? (26 - tmpDate.getDay()) + 7 : (26 - tmpDate.getDay()); //first monday in sep
  tmpDate.setFullYear(year, 11, 25);
  c_arrDataHolidays[c_arrDataHolidays.length] = "Christmas";
  c_arrDataHolidays[c_arrDataHolidays.length] = 11;
  c_arrDataHolidays[c_arrDataHolidays.length] = (tmpDate.getDay() == 0) ? 26 : (tmpDate.getDay() == 6) ? 24 : 25;
  tmpDate.setFullYear(year + 1, 0, 1);
  if (tmpDate.getDay() == 6) {
    c_arrDataHolidays[c_arrDataHolidays.length] = "New Years";
    c_arrDataHolidays[c_arrDataHolidays.length] = 11;
    c_arrDataHolidays[c_arrDataHolidays.length] = 31;
  }

}

function LoadCalendarYear(freq) {
  addCals();
  document.getElementById("prevyear").innerHTML = "&lt;-- " + (curyear - 1);
  document.getElementById("curyear").innerHTML = (curyear);
  document.getElementById("nextyear").innerHTML = (curyear + 1) + " --&gt;";
  for (mos = 0; mos < 12; ++mos) {
    LoadCalendarMonth(mos, curyear, freq);
  }
}

//xdate is in milli
function IsHoliday(xdate) {
  var tmpdate = new Date();
  var curMonth = getmofrommilli(xdate);
  var curDay = getdayfrommilli(xdate);
  tmpdate.setTime(xdate);
  return BankHoliday(tmpdate, false) || DSCHoliday(tmpdate, false);
}

function LoadCalendarMonth(month, year, freq) {
  var tmpdate = new Date();
  tmpdate.setFullYear(year, month, 1);
  days = tmpdate.getDay();
  for (i = 1; i <= days; ++i) {
    document.getElementById(months[month] + i).className = "blankdays";
    document.getElementById(months[month] + i).innerHTML = "&nbsp;";
  }

  for (i = 1; i <= c_arrMonthDays[month]; ++i) {
    var holidaytext = "";
    var alttext = "";
    var curday = new Date();
    curday.setFullYear(year, month, i);
    ++days;
    var cell = document.getElementById(months[month] + days);
    cell.innerHTML = "" + i;
    cell.className += " activeday";
    if (BankHoliday(curday, true)) {
      cell.title = holidayname;
      cell.className += " holiday";
      holidaytext = c_arrMonthNames[month] + " " + i + " is a bank holiday";
    } else if (DSCHoliday(curday, true)) {
      cell.title = holidayname;
      cell.className += " dscday";
      holidaytext = c_arrMonthNames[month] + " " + i + " is a bank and DSC holiday";
    }
    if (freq != "" && isapedt(curday)) {
      cell.className += " pedate";
      alttext = (holidaytext.length == 0) ? c_arrMonthNames[month] + " " + i + " is a pay ending date." : holidaytext + ", and a pay ending date.";
      cell.innerHTML = "<img src='/site/images/pedate.gif' alt='" + alttext + "' />";
    }
    if (freq != "" && isachkdt(curday)) {
      cell.className += " chkdate";
      alttext = (holidaytext.length == 0) ? c_arrMonthNames[month] + " " + i + " is a check date." : holidaytext + ", and a check date.";
      cell.innerHTML = "<img src='/site/images/chkdate.gif' alt='" + alttext + "' />";
    }

    if (cell.className.indexOf("chkdate") > -1 && cell.className.indexOf("pedate") > -1) {
      cell.className += " chkdtpedt";
      cell.innerHTML = "<img src='/site/images/chkpedate.gif' alt='" + c_arrMonthNames[month] + " " + i + " is a pay ending date and a check date.' />";
    }

    tmpdate.setFullYear(year, month, i);
  }

  blankrow = false;

  for (i = days + 1; i <= 42; ++i) {
    if (!blankrow && (i == 29 || i == 36))
      blankrow = true;
    if (blankrow && i == 29)
      document.getElementById(months[month] + "ftw").style.display = "none";
    if (blankrow && i == 36)
      document.getElementById(months[month] + "sxw").style.display = "none";
    document.getElementById(months[month] + i).className = (blankrow) ? "blankrow" : "blankdays";
    document.getElementById(months[month] + i).innerHTML = "&nbsp;";
  }
}

function addCals() {
  var c_arrWeekDayNames = new Array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');
  var c_arrWeekDayNamesAbrv = new Array('S', 'M', 'T', 'W', 'T', 'F', 'S');
  calDiv = document.getElementById("calendar");
  tmpstr = ""
  for (i = 0; i < 12; ++i) {
    tmpstr += '<div class="monthbox"><div class="month" id="' + months[i] + '">';
    tmpstr += '<div class="monthtitle">' + c_arrMonthNames[i] + '</div>';
    tmpstr += '<table class="daystable" cellspacing="0" >';
    tmpstr += '<tr class="dayheader">';
    for (j = 0; j < 7; ++j) {
      tmpstr += '<th class="' + months[i] + ' dayheader">' + c_arrWeekDayNamesAbrv[j] + '</th>';
    }
    tmpstr += '</tr>';
    boxcount = 1;
    for (j = 0; j < 6; ++j) {
      tmpstr += '<tr class="' + c_arrWeekNames[j] + '" id="' + months[i] + c_arrWeekNamesAbrv[j] + '">';
      for (k = 0; k < 7; ++k) {
        tmpstr += '<td class="' + months[i] + ' ' + c_arrWeekDayNames[k] + '" id="' + months[i] + boxcount + '">&nbsp;</td>';
        ++boxcount;
      }
      tmpstr += '</tr>';
    }
    tmpstr += '</table></div></div>';
  }
  calDiv.innerHTML = tmpstr;
}

