
/*
 * JAWStats 0.7 Web Statistics
 *
 * Copyright (c) 2009 Jon Combe (jawstats.com)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

var oPaging = {
  oKeywords:{ iCurrPage:0, iRowCount:0, iRowsPerPage:15, sSort:"freqDESC" },
  oKeyphrases:{ iCurrPage:0, iRowCount:0, iRowsPerPage:15, sSort:"freqDESC" }
};

function DrawGraph_EachYear() {
  var aItem = [];
  var aValue = [];
  var aInitial = [];
 
  var cur_year = oStatistics.oAllMonths.aData[0].dtDate.getFullYear();
  var cur_emails = 0;

  for (var iIndex in oStatistics.oAllMonths.aData) { 
    var year = oStatistics.oAllMonths.aData[iIndex].dtDate.getFullYear();

    if ( year == cur_year ) {
	cur_emails += parseInt(oStatistics.oAllMonths.aData[iIndex].iPages);
    } else {
    	aItem.push( cur_year );
	aInitial.push( cur_year.toString().substr(2) );
    	aValue.push( cur_emails );
	cur_year = year;
	cur_emails = parseInt(oStatistics.oAllMonths.aData[iIndex].iPages);
    }
  }
  aItem.push( cur_year );
  aInitial.push( cur_year.toString().substr(2) );
  aValue.push( cur_emails );
  DrawBar(aItem, aValue, aInitial);
}

function DrawGraph_AllMonths() {
  var aItem = [];
  var aValue = [];
  for (var iIndex in oStatistics.oAllMonths.aData) {
      /*    aItem.push(Lang(gc_aMonthName[oStatistics.oAllMonths.aData[iIndex].dtDate.getMonth()].substr(0,3)) + " '" +
               (oStatistics.oAllMonths.aData[iIndex].dtDate.getFullYear()).toString().substr(2));*/
      aItem.push(oStatistics.oAllMonths.aData[iIndex].dtDate);
      aValue.push(oStatistics.oAllMonths.aData[iIndex].iPages);
  }
  DrawGraph(aItem, aValue, [], "time");
}

function DrawGraph_ThisMonth() {
  var aItem = [];
  var aValue = [];
  var aInitial = [];

  // populate days
  var iDaysInMonth = (new Date(g_iYear, g_iMonth, 0)).getDate();
  var iDayOfWeek = (new Date(g_iYear, (g_iMonth - 1), 1)).getDay();
  for (var iDay = 0; iDay < iDaysInMonth; iDay++) {
    aItem.push(Lang((iDay + 1) + DateSuffix(iDay + 1)));
    aValue.push(0);
    aInitial.push(Lang(gc_aDayName[iDayOfWeek].substr(0, 3)));

    // day of week
    iDayOfWeek++;
    if (iDayOfWeek > 6) {
      iDayOfWeek = 0;
    }
  }

  // update values we know about
  for (var iIndex in oStatistics.oThisMonth.aData) {
    iDay = (oStatistics.oThisMonth.aData[iIndex].dtDate.getDate() - 1);
    aValue[iDay] = oStatistics.oThisMonth.aData[iIndex].iPages;
  }
  DrawBar(aItem, aValue, aInitial);
}

function DrawGraph_Time() {
  var aItem = [];
  var aValue = [];
  for (var iRow in oStatistics.oTime.aData) {
    oRow = oStatistics.oTime.aData[iRow];
    sHour = oRow.iHour;
    if (oRow.iHour < 10) {
      sHour = ("0" + sHour)
    }
    aItem.push(sHour);
    aValue.push(oRow.iPages);
  }
  DrawGraph(aItem, aValue, [], null);
}

function DrawPage(sPage) {
    $("#content").fadeOut(g_iFadeSpeed, function() {
	    g_sCurrentView = sPage;
	    var aPage = sPage.split(".");
	    switch (aPage[0]) {
	    case "allmonths":
		if (typeof oStatistics.oAllMonths == "undefined") {
		    PopulateData_AllMonths(sPage);
		    return false;
		}
		PageLayout_AllMonths(aPage[1]);
		break;
	    case "country":
		if (typeof oStatistics.oCountry == "undefined") {
		    PopulateData_Country(sPage);
		    return false;
		}
		PageLayout_Country(aPage[1]);
		break;
	    case "hosts":
		if (typeof oStatistics.oHosts == "undefined") {
		    PopulateData_Hosts(sPage);
	    return false;
		}
		PageLayout_EmailHosts(aPage[1]);
		break;
	    case "senders":
		if (typeof oStatistics.oSenders == "undefined") {
		    PopulateData_Senders(sPage);
	    return false;
		}
		PageLayout_EmailSenders(aPage[1]);
		break;
	    case "recipients":
		if (typeof oStatistics.oRecipients == "undefined") {
		    PopulateData_Recipients(sPage);
		    return false;
		}
		PageLayout_EmailRecipients(aPage[1]);
		break;
	    case "status":
		if (aPage[1] == "404") {
		    if (typeof oStatistics.oStatus404 == "undefined") {
			PopulateData_Status404(sPage);
			return false;
		    }
		} else {
		    if (typeof oStatistics.oStatus == "undefined") {
			PopulateData_Status(sPage);
			return false;
		    }
		}
		PageLayout_Status(aPage[1]);
		break;
	    case "thismonth":
		if (typeof oStatistics.oThisMonth == "undefined") {
		    PopulateData_ThisMonth(sPage);
		    return false;
		}
		PageLayout_ThisMonth(aPage[1]);
		break;
	    case "time":
		if (typeof oStatistics.oTime == "undefined") {
		    PopulateData_Time(sPage);
		    return false;
		}
		PageLayout_Time();
		break;
	    }
	});
}

function DrawPie_Country(sContinent) {
  // get values
  if (typeof sContinent == "undefined") {
    iTotalPages = oStatistics.oCountry.iTotalPages;
  } else {
    iTotalPages = oStatistics.oCountry.oContinent[sContinent].iTotalPages;
  }
  aData = oStatistics.oCountry.aData;

  // build arrays
  var aItem = [];
  var aValue = [];
  var iRunningTotal = 0;
  var iCount = 0;
  for (var iIndex in aData) {
    if (iCount < 6) {
      if ((typeof sContinent == "undefined") || (aData[iIndex].sContinent == sContinent)) {
        aItem.push(Lang(aData[iIndex].sCountryName));
        aValue.push(aData[iIndex].iPages);
        iRunningTotal += aData[iIndex].iPages;
        iCount++;
      }
    }
  }
  if (iTotalPages > iRunningTotal) {
    aItem.push(Lang("Other Countries"));
    aValue.push(iTotalPages - iRunningTotal);
  }
  DrawPie(iTotalPages, aItem, aValue);
}

function DrawPie_CountryContinent() {
  // this section is an anomaly whereby the continents need to be sorted by size before being passsed to the flash
  // thankfully there are only 6 (we are interested in)
  var aTemp = [];
  for (var sContinent in gc_aContinents) {
    aTemp.push({ "sContinent" : sContinent,
                 "iPages"     : oStatistics.oCountry.oContinent[sContinent].iTotalPages });
  }
  aTemp.sort(Sort_Pages);

  // pass across to simpler array format
  var iTotalPages = oStatistics.oCountry.iTotalPages;
  var aItem = [];
  var aValue = [];
  var iRunningTotal = 0;
  for (var iIndex in aTemp) {
    aItem.push(Lang(aTemp[iIndex].sContinent));
    aValue.push(aTemp[iIndex].iPages);
    iRunningTotal += aTemp[iIndex].iPages;
  }
  if (iTotalPages > iRunningTotal) {
    aItem.push(Lang("Other"));
    aValue.push(iTotalPages - iRunningTotal);
  }
  DrawPie(iTotalPages, aItem, aValue);
}

function DrawPie_Emails(aData, iTotal, sItemName) {
  var aItem = [];
  var aValue = [];
  var iRunningTotal = 0;
  var iCount = 0;
  for (var iIndex in aData) {
    if (iCount < 6) {
      aItem.push(aData[iIndex].sAddress);
      aValue.push(aData[iIndex][sItemName]);
      iRunningTotal += aData[iIndex][sItemName];
    }
    iCount++;
  }
  if (iTotal > iRunningTotal) {
    aItem.push(Lang("Other Adresses"));
    aValue.push(iTotal - iRunningTotal);
  }
  DrawPie(iTotal, aItem, aValue);
}

function DrawPie_Status() {
  var aItem = [];
  var aValue = [];
  var iRunningTotal = 0;
  var iCount = 0;
  for (var iIndex in oStatistics.oStatus.aData) {
    if (iCount < 6) {
      if (oStatistics.oStatus.aData[iIndex].sDescription != "&nbsp;") {
        aItem.push(oStatistics.oStatus.aData[iIndex].sCode + ": " +
                   Lang(oStatistics.oStatus.aData[iIndex].sDescription));
      } else {
        aItem.push(oStatistics.oStatus.aData[iIndex].sCode);
      }
      aValue.push(oStatistics.oStatus.aData[iIndex].iHits);
      iRunningTotal += oStatistics.oStatus.aData[iIndex].iHits;
    }
    iCount++;
  }
  if (oStatistics.oStatus.iTotalHits > iRunningTotal) {
    aItem.push(Lang("Other Status Codes"));
    aValue.push(oStatistics.oStatus.iTotalHits - iRunningTotal);
  }
  DrawPie(oStatistics.oStatus.iTotalHits, aItem, aValue);
}

function DrawPie_Status404() {
  var aItem = [];
  var aValue = [];
  var iRunningTotal = 0;
  var iCount = 0;
  for (var iIndex in oStatistics.oStatus404.aData) {
    if (iCount < 6) {
      aItem.push(oStatistics.oStatus404.aData[iIndex].sURL.replace(/&#8203;/g, ""));
      aValue.push(oStatistics.oStatus404.aData[iIndex].iHits);
      iRunningTotal += oStatistics.oStatus404.aData[iIndex].iHits;
    }
    iCount++;
  }
  if (oStatistics.oStatus404.iTotalHits > iRunningTotal) {
    aItem.push("Other URLs");
    aValue.push(oStatistics.oStatus404.iTotalHits - iRunningTotal);
  }
  DrawPie(oStatistics.oStatus404.iTotalHits, aItem, aValue);
}

function DrawTable_AllMonths(sPage) {
  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>";
  if (sPage == "all") {
    sHTML += "<th width=\"16%\">" + Lang("Month") + "</th>";
  } else {
    sHTML += "<th width=\"16%\">" + Lang("Year") + "</th>";
  }
  sHTML += "<th width=\"12%\">" + Lang("Total Emails") + "</th>" +
           "<th width=\"12%\">" + Lang("Emails per Day") + "</th>" +
           "<th width=\"12%\" class=\"noborder\">" + Lang("BW") + "</th>" +
           "</tr></thead>\n" +
           "<tbody>";

  // create table body
  aHTML = new Array();
  var iTotalEmails   = 0;
  var iTotalBW       = 0;
  var iAnnualEmails  = 0;
  var iAnnualBW      = 0;
  var iCurrentYear   = oStatistics.oAllMonths.aData[0].iYear;

  for (var iRow in oStatistics.oAllMonths.aData) {
    oRow = oStatistics.oAllMonths.aData[iRow];

    // create single values
    var iEmails      = parseInt(oRow.iPages);
    var iBW          = parseInt(oRow.iBW);
    var iDaysInMonth = parseFloat(oRow.iDaysInMonth);

    // sum totals
    iTotalEmails   += iEmails;
    iTotalBW       += iBW;
    iAnnualEmails   += iEmails;
    iAnnualBW      += iBW;
    iCurrentYear   = oRow.iYear;

    // create table
    switch (sPage) {
      case "all":
        if ((g_iMonth == oRow.iMonth) && (g_iYear == oRow.iYear)) {
          var sHTMLRow = "<tr class=\"highlight\">";
        } else {
          var sHTMLRow = "<tr>";
        }
        sHTMLRow += "<td><span class=\"hidden\">" + oRow.dtDate.valueOf() + "</span>" + Lang(gc_aMonthName[oRow.iMonth - 1]) + " " + oRow.iYear + "</td>" +
                    "<td class=\"right\">" + NumberFormat(iEmails, 0) + "</td>" +
                    "<td class=\"right\">" + NumberFormat((iEmails / iDaysInMonth), 1) + "</td>" + 
	                    "<td class=\"right\">" + DisplayBandwidth(iBW) + "</td>" +
                    "</tr>\n";
        aHTML.push(sHTMLRow);
        break;
      case "year":
        //if ((iCurrentYear != oRow.iYear) || (iRow == (oStatistics.oAllMonths.aData.length - 1))) {
        if ((oRow.iMonth == 12) || (iRow == (oStatistics.oAllMonths.aData.length - 1))) {
          var sHTMLRow = "<tr>" +
                         "<td>" + iCurrentYear + "</td>" +
                         "<td class=\"right\">" + NumberFormat(iAnnualEmails) + "</td>" +
                         "<td class=\"right\">" + NumberFormat((iAnnualEmails / oStatistics.oAllMonths.aYearDayCount[iCurrentYear]), 1) + "</td>"  +
	                 "<td class=\"right\">" + DisplayBandwidth(iAnnualBW) + "</td>" +
                         "</tr>\n";
          aHTML.push(sHTMLRow);

          // reset values
          iAnnualEmails  = 0;
          iAnnualBW      = 0;
        }
        break;
    }
  }

  // output
  if (aHTML.length > 0) {
    sHTML = (sHTML + aHTML.join("\n") + "</tbody><tfoot><tr>" +
             "<td class=\"noborder\">&nbsp;</td>" +
             "<td class=\"noborder right\">" + NumberFormat(iTotalEmails, 0) + "</td>" +
             "<td class=\"noborder right\">&nbsp;</td>" +
             "<td class=\"noborder right\">" + DisplayBandwidth(iTotalBW) + "</td>" +
             "</tr></tfoot></table>")
    return ( [ true, sHTML ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"7\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_Country(sContinent) {
  // get values
  if (typeof sContinent == "undefined") {
    iTotalPages = oStatistics.oCountry.iTotalPages;
    iTotalHits  = oStatistics.oCountry.iTotalHits;
    iTotalBW    = oStatistics.oCountry.iTotalBW;
  } else {
    iTotalPages = oStatistics.oCountry.oContinent[sContinent].iTotalPages;
    iTotalHits  = oStatistics.oCountry.oContinent[sContinent].iTotalHits;
    iTotalBW    = oStatistics.oCountry.oContinent[sContinent].iTotalBW;
  }
  aData       = oStatistics.oCountry.aData;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
		          "<th>&nbsp;</th>" +
              "<th>" + Lang("Country") + "</th>" +
              "<th>" + Lang("EMails") + "</th>" +
              "<th>%</th>" +
              "<th>" + Lang("Hits") + "</th>" +
              "<th>%</th>" +
		          "<th>" + Lang("Bandwidth") + "</th>" +
		          "<th class=\"noborder\">%</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  var aHTML = new Array();
  for (var iRow in aData) {
    if (aData[iRow].sContinent == "Other") {
      aData[iRow].sCountryCode = "trans";
    }
    if ((typeof sContinent == "undefined") || (aData[iRow].sContinent == sContinent)) {
      aHTML.push("<tr>" +
                 "<td class=\"countryflag\"><img src=\"themes/" + sThemeDir + "/flags/" + aData[iRow].sCountryCode + ".gif\" alt=\"" + aData[iRow].sCountryName + "\" /></td>" +
                 "<td>" + Lang(aData[iRow].sCountryName) + "</td>" +
                 "<td class=\"noborder right\">" + NumberFormat(aData[iRow].iPages, 0) + "</td>" +
                 "<td class=\"right\">" + (SafeDivide(aData[iRow].iPages, iTotalPages) * 100).toFixed(1) + "%</td>" +
                 "<td class=\"noborder right\">" + NumberFormat(aData[iRow].iHits, 0) + "</td>" +
                 "<td class=\"right\">" + ((aData[iRow].iHits / iTotalHits) * 100).toFixed(1) + "%</td>" +
                 "<td class=\"noborder right\">" + DisplayBandwidth(aData[iRow].iBW) + "</td>" +
                 "<td class=\"noborder right\">" + ((aData[iRow].iBW / iTotalBW) * 100).toFixed(1) + "%</td>" +
                 "</tr>");
    }
  }

  // output
  if (aHTML.length > 0) {
    return ( [ true, (sHTML + aHTML.join("\n") + "</tbody></table>") ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"8\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_CountryContinent() {
  // get values
  var iTotalPages = oStatistics.oCountry.iTotalPages;
  var iTotalHits  = oStatistics.oCountry.iTotalHits;
  var iTotalBW    = oStatistics.oCountry.iTotalBW;
  var iOtherPages = iTotalPages;
  var iOtherHits  = iTotalHits;
  var iOtherBW    = iTotalBW;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th>" + Lang("Continent") + "</th>" +
              "<th>" + Lang("Pages") + "</th>" +
              "<th>%</th>" +
              "<th>" + Lang("Hits") + "</th>" +
              "<th>%</th>" +
		          "<th>" + Lang("Bandwidth") + "</th>" +
		          "<th class=\"noborder\">%</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  aHTML = new Array();
  for (var sContinent in gc_aContinents) {
    oC = oStatistics.oCountry.oContinent[sContinent];
    iOtherPages -= oC.iTotalPages;
    iOtherHits  -= oC.iTotalHits;
    iOtherBW    -= oC.iTotalBW;
    aHTML.push("<tr>" +
               "<td>" + Lang(sContinent) + " &nbsp;<span class=\"fauxlink tiny\" onclick=\"DrawPage('country." + sContinent + "');\">&raquo;</span></td>" +
               "<td class=\"right\">" + NumberFormat(oC.iTotalPages, 0) + "</td>" +
               "<td class=\"right\">" + ((oC.iTotalPages / iTotalPages) * 100).toFixed(1) + "%</td>" +
               "<td class=\"right\">" + NumberFormat(oC.iTotalHits, 0) + "</td>" +
               "<td class=\"right\">" + ((oC.iTotalHits / iTotalHits) * 100).toFixed(1) + "%</td>" +
               "<td class=\"right\">" + DisplayBandwidth(oC.iTotalBW) + "</td>" +
               "<td class=\"noborder right\">" + ((oC.iTotalBW / iTotalBW) * 100).toFixed(1) + "%</td>" +
               "</tr>\n");
  }

  // add "other" row
  aHTML.push("<tr>" +
             "<td>" + Lang("Other") + "&nbsp;<span class=\"fauxlink tiny\" onclick=\"DrawPage('country.Other');\">&raquo;</span></td>" +
             "<td class=\"right\">" + NumberFormat(iOtherPages, 0) + "</td>" +
             "<td class=\"right\">" + ((iOtherPages / iTotalPages) * 100).toFixed(1) + "%</td>" +
             "<td class=\"right\">" + NumberFormat(iOtherHits, 0) + "</td>" +
             "<td class=\"right\">" + ((iOtherHits / iTotalHits) * 100).toFixed(1) + "%</td>" +
             "<td class=\"right\">" + DisplayBandwidth(iOtherBW) + "</td>" +
             "<td class=\"noborder right\">" + ((iOtherBW / iTotalBW) * 100).toFixed(1) + "%</td>" +
             "</tr>\n");

  // output
  return (sHTML + aHTML.join("\n") + "</tbody></table>");
}

function DrawTable_Filetypes() {
  // get values
  iTotalHits      = oStatistics.oFiletypes.iTotalHits;
  iTotalBW        = oStatistics.oFiletypes.iTotalBW;
  iTotalNonCompBW = oStatistics.oFiletypes.iTotalNonCompBW;
  iTotalCompBW    = oStatistics.oFiletypes.iTotalCompBW;
  aData           = oStatistics.oFiletypes.aData;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th>" + Lang("Filetype") + "</th>" +
              "<th>" + Lang("Description") + "</th>" +
              "<th>" + Lang("Hits") + "</th>" +
              "<th>&nbsp;</th>" +
		          "<th>" + Lang("Bandwidth") + "</th>" +
		          "<th>&nbsp;</th>" +
		          "<th class=\"noborder\">" + Lang("Average Size") + "</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  aHTML = new Array();
  for (var iRow in aData) {
    aHTML.push("<tr>" +
               "<td>" + oStatistics.oFiletypes.aData[iRow].sFiletype + "</td>" +
               "<td>" + Lang(oStatistics.oFiletypes.aData[iRow].sDescription) + "</td>" +
               "<td class=\"right\">" + NumberFormat(oStatistics.oFiletypes.aData[iRow].iHits, 0) + "</td>" +
               "<td class=\"right\">" + ((oStatistics.oFiletypes.aData[iRow].iHits / iTotalHits) * 100).toFixed(1) + "%</td>" +
               "<td class=\"right\">" + DisplayBandwidth(oStatistics.oFiletypes.aData[iRow].iBW) + "</td>" +
               "<td class=\"right\">" + ((oStatistics.oFiletypes.aData[iRow].iBW / iTotalBW) * 100).toFixed(1) + "%</td>" +
               "<td class=\"noborder right\">" + DisplayBandwidth(oStatistics.oFiletypes.aData[iRow].iBW / oStatistics.oFiletypes.aData[iRow].iHits) + "</td>" +
               "</tr>\n");
  }

  // output
  if (aHTML.length > 0) {
    return ( [ true, (sHTML + aHTML.join("\n") + "</tbody></table>") ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"7\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_EmailHost(aData) {
  // get values
  var iTotalEmails    = oStatistics.oHosts.iTotalEmails;
  var iTotalBW        = oStatistics.oHosts.iTotalBW;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th>" + Lang("Host") + "</th>" +
              "<th>" + Lang("Emails") + "</th>" +
              "<th>&nbsp;</th>" +
              "<th>" + Lang("Bandwidth") + "</th>" +
              "<th class=\"noborder\">&nbsp;</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  var aHTML = [];
  for (var iRow in aData) {
    aHTML.push("<tr>" +
               "<td>" + aData[iRow].sAddress + "</td>" +
               "<td class=\"right\">" + NumberFormat(aData[iRow].iEmails, 0) + "</td>" +
               "<td class=\"right\">" + NumberFormat(SafeDivide(aData[iRow].iEmails, iTotalEmails) * 100, 1) + "%</td>" +
               "<td class=\"right\">" + DisplayBandwidth(aData[iRow].iBW) + "</td>" +
               "<td class=\"right\">" + NumberFormat(SafeDivide(aData[iRow].iBW, iTotalBW) * 100, 1) + "%</td>" +
               "</tr>\n");
  }

  // output
  if (aHTML.length > 0) {
    return ( [ true, (sHTML + aHTML.join("\n") + "</tbody></table>") ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"9\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_EmailSender(aData) {
  // get values
  var iTotalEmails    = oStatistics.oSenders.iTotalEmails;
  var iTotalBW        = oStatistics.oSenders.iTotalBW;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th>" + Lang("Sender") + "</th>" +
              "<th>" + Lang("Emails") + "</th>" +
              "<th>&nbsp;</th>" +
              "<th>" + Lang("Bandwidth") + "</th>" +
              "<th class=\"noborder\">&nbsp;</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  var aHTML = [];
  for (var iRow in aData) {
    aHTML.push("<tr>" +
               "<td>" + aData[iRow].sAddress + "</td>" +
               "<td class=\"right\">" + NumberFormat(aData[iRow].iEmails, 0) + "</td>" +
               "<td class=\"right\">" + NumberFormat(SafeDivide(aData[iRow].iEmails, iTotalEmails) * 100, 1) + "%</td>" +
               "<td class=\"right\">" + DisplayBandwidth(aData[iRow].iBW) + "</td>" +
               "<td class=\"right\">" + NumberFormat(SafeDivide(aData[iRow].iBW, iTotalBW) * 100, 1) + "%</td>" +
               "</tr>\n");
  }

  // output
  if (aHTML.length > 0) {
    return ( [ true, (sHTML + aHTML.join("\n") + "</tbody></table>") ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"9\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_EmailRecipient(aData) {
  // get values
  var iTotalEmails    = oStatistics.oRecipients.iTotalEmails;
  var iTotalBW        = oStatistics.oRecipients.iTotalBW;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th>" + Lang("Recipient") + "</th>" +
              "<th>" + Lang("Emails") + "</th>" +
              "<th>&nbsp;</th>" +
              "<th>" + Lang("Bandwidth") + "</th>" +
              "<th class=\"noborder\">&nbsp;</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  var aHTML = [];
  for (var iRow in aData) {
    aHTML.push("<tr>" +
               "<td>" + aData[iRow].sAddress + "</td>" +
               "<td class=\"right\">" + NumberFormat(aData[iRow].iEmails, 0) + "</td>" +
               "<td class=\"right\">" + NumberFormat(SafeDivide(aData[iRow].iEmails, iTotalEmails) * 100, 1) + "%</td>" +
               "<td class=\"right\">" + DisplayBandwidth(aData[iRow].iBW) + "</td>" +
               "<td class=\"right\">" + NumberFormat(SafeDivide(aData[iRow].iBW, iTotalBW) * 100, 1) + "%</td>" +
               "</tr>\n");
  }

  // output
  if (aHTML.length > 0) {
    return ( [ true, (sHTML + aHTML.join("\n") + "</tbody></table>") ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"9\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_Status() {
  // get values
  iTotalHits      = oStatistics.oStatus.iTotalHits;
  iTotalBW        = oStatistics.oStatus.iTotalBW;
  aData           = oStatistics.oStatus.aData;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th>" + Lang("Code") + "</th>" +
              "<th>" + Lang("Description") + "</th>" +
              "<th>" + Lang("Messages") + "</th>" +
              "<th>&nbsp;</th>" +
		          "<th>" + Lang("Bandwidth") + "</th>" +
		          "<th>&nbsp;</th>" +
		          "<th class=\"noborder\">" + Lang("Average Size") + "</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  aHTML = new Array();
  for (var iRow in aData) {
    aHTML.push("<tr>" +
               "<td>" + oStatistics.oStatus.aData[iRow].sCode + "</td>" +
               "<td>" + Lang(oStatistics.oStatus.aData[iRow].sDescription) + "</td>" +
               "<td class=\"right\">" + NumberFormat(oStatistics.oStatus.aData[iRow].iHits, 0) + "</td>" +
               "<td class=\"right\">" + ((oStatistics.oStatus.aData[iRow].iHits / iTotalHits) * 100).toFixed(1) + "%</td>" +
               "<td class=\"right\">" + DisplayBandwidth(oStatistics.oStatus.aData[iRow].iBW) + "</td>" +
               "<td class=\"right\">" + ((oStatistics.oStatus.aData[iRow].iBW / iTotalBW) * 100).toFixed(1) + "%</td>" +
               "<td class=\"noborder right\">" + DisplayBandwidth(oStatistics.oStatus.aData[iRow].iBW / oStatistics.oStatus.aData[iRow].iHits) + "</td>" +
               "</tr>\n");
  }

  // output
  if (aHTML.length > 0) {
    return ( [ true, (sHTML + aHTML.join("\n") + "</tbody></table>") ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"7\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_Status404() {
  // get values
  iTotalHits      = oStatistics.oStatus404.iTotalHits;
  aData           = oStatistics.oStatus404.aData;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th>" + Lang("URL") + "</th>" +
              "<th>" + Lang("Hits") + "</th>" +
              "<th>" + Lang("Referrer") + "</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  aHTML = new Array();
  var sReferrer = "";
  for (var iRow in aData) {
    if (oStatistics.oStatus404.aData[iRow].sReferrer == "-") {
      sReferrer = "&nbsp;";
    } else {
      sReferrer = ("<a href=\"" + oStatistics.oStatus404.aData[iRow].sReferrer + "\" target=\"_blank\">" + oStatistics.oStatus404.aData[iRow].sReferrerVisible + "</a>");
    }
    aHTML.push("<tr>" +
               "<td>" + oStatistics.oStatus404.aData[iRow].sURL + "</td>" +
               "<td class=\"right\">" + NumberFormat(oStatistics.oStatus404.aData[iRow].iHits, 0) + "</td>" +
               "<td>" + sReferrer + "</td>" +
               "</tr>\n");
  }

  // output
  if (aHTML.length > 0) {
    return ( [ true, (sHTML + aHTML.join("\n") + "</tbody></table>") ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"3\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_ThisMonth() {
  // get values
  iTotalEmails     = oStatistics.oThisMonth.iTotalPages;
  iTotalBW        = oStatistics.oThisMonth.iTotalBW;
  aData           = oStatistics.oThisMonth.aData;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th width=\"15%\">" + Lang("Day") + "</th>" +
              "<th width=\"14%\">" + Lang("Date") + "</th>" +
              "<th width=\"9%\" class=\"noborder\">" + Lang("Emails") + "</th>" +
              "<th width=\"11%\">" + Lang("per Mail") + "</th>" +
              "<th width=\"9%\" class=\"noborder\">" + Lang("BW") + "</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  aHTML = new Array();
  for (var iRow in aData) {
    oRow = oStatistics.oThisMonth.aData[iRow];
	  sVisibleDate = (oRow.dtDate.getDate() + " " +
	                  Lang(gc_aMonthName[oRow.dtDate.getMonth()].substr(0,3)) + " '" +
	                  oRow.dtDate.getFullYear().toString().substr(2));
	  if (oRow.dtDate.getDay() == 0) {
	    sRowStyle = " class=\"sunday\"";
	  } else if (oRow.dtDate.getDay() == 6) {
	    sRowStyle = " class=\"saturday\"";
	  } else {
	    sRowStyle = "";
	  }
    aHTML.push("<tr" + sRowStyle + ">" +
               "<td><span class=\"hidden\">" + oRow.dtDate.getDay() + "</span>" + Lang(gc_aDayName[oRow.dtDate.getDay()]) + "</td>" +
               "<td><span class=\"hidden\">" + oRow.dtDate.valueOf() + "</span>" + sVisibleDate + "</td>" +
               "<td class=\"right\">" + NumberFormat(oRow.iPages, 0) + "</td>" +
               "<td class=\"right\">" + DisplayBandwidth((SafeDivide(oRow.iBW, oRow.iPages))) + "</td>" +
	       "<td class=\"noborder right\">" + DisplayBandwidth(oRow.iBW) + "</td>" +
               "</tr>\n");
  }

  // output
  if (aHTML.length > 0) {
    sHTML = (sHTML + aHTML.join("\n") + "</tbody><tfoot><tr>" +
             "<td colspan=\"3\" class=\"noborder right\">" + NumberFormat(iTotalEmails, 0) + "</td>" +
             "<td class=\"noborder right\">" + DisplayBandwidth(iTotalBW) + "</td>" +
             "</tr></tfoot></table>")
    return ( [ true, sHTML ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"10\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }
}

function DrawTable_Time() {
  // get values
  var iTotalEmails    = oStatistics.oTime.iTotalPages;
  var iTotalBW        = oStatistics.oTime.iTotalBW;
  var iTotalNVEmails  = oStatistics.oTime.iTotalNVPages;
  var iTotalNVBW      = oStatistics.oTime.iTotalNVBW;

  // create header
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th>" + Lang("Hour") + "</th>" +
              "<th class=\"noborder\">" + Lang("Emails") + "</th>" +
              "<th class=\"noborder right\">%</th>" +
              "<th class=\"right\">+/-</th>" +
              "<th class=\"noborder\">" + Lang("BW") + "</th>" +
              "<th class=\"noborder right\">%</th>" +
              "<th class=\"right\">+/-</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  var aHTML     = [];
  var iAvgEmails = (iTotalEmails / 24);
  var iAvgBW    = (iTotalBW / 24);
  for (var iRow in oStatistics.oTime.aData) {
    var oRow = oStatistics.oTime.aData[iRow];
    var sHour = oRow.iHour;
    if (oRow.iHour < 10) {
      sHour = ("0" + sHour)
    }

    // +/- values
    var sEmailsDiff = Difference(oRow.iPages, iAvgEmails);
    var sBWDiff = Difference(oRow.iBW, iAvgBW);

    // create table
    aHTML.push("<tr>" +
               "<td>" + sHour + "</td>" +
               "<td class=\"right\">" + NumberFormat(oRow.iPages, 0) + "</td>" +
               "<td class=\"right\">" + NumberFormat((SafeDivide(oRow.iPages, iTotalEmails) * 100), 1) + "%</td>" +
               "<td class=\"right\">" + sEmailsDiff + "</td>" +
               "<td class=\"right\">" + DisplayBandwidth(oRow.iBW) + "</td>" +
               "<td class=\"right\">" + NumberFormat((SafeDivide(oRow.iBW, iTotalBW) * 100), 1) + "%</td>" +
               "<td class=\"right\">" + sBWDiff + "</td>" +
               "</tr>\n");
  }

  // output
  if (aHTML.length > 0) {
    sHTML = (sHTML + aHTML.join("\n") + "</tbody><tfoot><tr>" +
             "<td class=\"noborder\">&nbsp;</td>" +
             "<td class=\"noborder right\">" + NumberFormat(iTotalEmails, 0) + "</td>" +
             "<td class=\"noborder\">&nbsp;</td>" +
             "<td class=\"noborder\">&nbsp;</td>" +
             "<td class=\"noborder right\">" + DisplayBandwidth(iTotalBW) + "</td>" +
             "<td class=\"noborder\">&nbsp;</td>" +
             "<td class=\"noborder\">&nbsp;</td>" +
             "</tr></tfoot></table>")
    return ( [ true, sHTML ] );
  } else {
    return ( [ false, (sHTML + "<tr><td class=\"center\" colspan=\"4\">" + Lang("There is no data to display") + "</td></tr></tbody></table>") ] );
  }

  function Difference(iValue, iAverage) {
    if (iValue == iAverage) {
      return "-";
    } else {
      if (iValue > iAverage) {
        return ("<span class=\"tiny positive\">+" + NumberFormat((SafeDivide((iValue - iAverage), iAverage) * 100), 1) + "%</span>");
      } else {
        return ("<span class=\"tiny negative\">-" + NumberFormat((SafeDivide((iAverage - iValue), iAverage) * 100), 1) + "%</span>");
      }
    }
  }
}

function Lang(sPhrase) {
  return (oTranslation[sPhrase] || sPhrase);
}

function Misc_ThisMonthCalendar(sHeadline, sSubMenu, sDataItem) {
  // create sum arrays
  var aWeek = [];
  var aDay = [];
  for (var iIndex = 0; iIndex < 7; iIndex++) {
    aDay[iIndex] = { iCount:0, iTotal:0 };
  }
  var iTotal = 0;

  // calculate dates
  var iFirstWeek = getWeekNr(oStatistics.oThisMonth.aData[0].dtDate);
  var dtLastDayOfMonth = new Date(oStatistics.oThisMonth.aData[0].dtDate.getFullYear(),
                                  (oStatistics.oThisMonth.aData[0].dtDate.getMonth() + 1),
                                  0);
  var iLastWeek = getWeekNr(dtLastDayOfMonth);

  // create table
  var sHTML = "<table class=\"calendar\"><tbody>" +
              "<tr>" +
              "<td class=\"labelTop\">&nbsp;</td>" +
              "<td class=\"labelTop\">" + Lang("Monday") + "</td>" +
              "<td class=\"labelTop\">" + Lang("Tuesday") + "</td>" +
              "<td class=\"labelTop\">" + Lang("Wednesday") + "</td>" +
              "<td class=\"labelTop\">" + Lang("Thursday") + "</td>" +
              "<td class=\"labelTop\">" + Lang("Friday") + "</td>" +
              "<td class=\"labelTop\">" + Lang("Saturday") + "</td>" +
              "<td class=\"labelTop\">" + Lang("Sunday") + "</td>" +
              "<td class=\"labelTopSpacer\">&nbsp;</td>" +
              "<td class=\"labelTop\">" + Lang("Week Total") + "</td>" +
              "<td class=\"labelTop\">" + Lang("Daily Average") + "</td>" +
              "</tr>";
  for (var iIndex = iFirstWeek; iIndex <= iLastWeek; iIndex++) {
    aWeek[iIndex] = { iCount:0, iTotal:0 };
    sHTML += "<tr>" +
             "<td id=\"calWeek" + iIndex + "\" class=\"labelSide\">" + Lang("Week") + ":&nbsp;" + iIndex + "</td>" +
             "<td id=\"calDay1-" + iIndex + "\">&nbsp;</td>" +
             "<td id=\"calDay2-" + iIndex + "\">&nbsp;</td>" +
             "<td id=\"calDay3-" + iIndex + "\">&nbsp;</td>" +
             "<td id=\"calDay4-" + iIndex + "\">&nbsp;</td>" +
             "<td id=\"calDay5-" + iIndex + "\">&nbsp;</td>" +
             "<td id=\"calDay6-" + iIndex + "\">&nbsp;</td>" +
             "<td id=\"calDay0-" + iIndex + "\">&nbsp;</td>" +
             "<td>&nbsp;</td>" +
             "<td id=\"calTotWk" + iIndex + "\" class=\"calTotWk\">&nbsp;</td>" +
             "<td id=\"calAvgWk" + iIndex + "\" class=\"calAvgWk\">&nbsp;</td>" +
             "</tr>";
  }
  sHTML += "<tr>" +
           "<td>&nbsp;</td>" +
           "<td colspan=\"7\" class=\"calGraph\"><div id=\"graph\">&nbsp</div>&nbsp;</td>" +
           "<td colspan=\"3\">&nbsp;</td>" +
           "</tr><tr>" +
           "<td class=\"labelSide\">" + Lang("Day of Week Total") + "</td>" +
           "<td id=\"calTotDay1\" class=\"calTotDay\">&nbsp;</td>" +
           "<td id=\"calTotDay2\" class=\"calTotDay\">&nbsp;</td>" +
           "<td id=\"calTotDay3\" class=\"calTotDay\">&nbsp;</td>" +
           "<td id=\"calTotDay4\" class=\"calTotDay\">&nbsp;</td>" +
           "<td id=\"calTotDay5\" class=\"calTotDay\">&nbsp;</td>" +
           "<td id=\"calTotDay6\" class=\"calTotDay\">&nbsp;</td>" +
           "<td id=\"calTotDay0\" class=\"calTotDay\">&nbsp;</td>" +
           "<td>&nbsp;</td>" +
           "<td colspan=\"2\" id=\"calTotMonth\" class=\"calTotDay\">&nbsp;</td>" +
           "</tr><tr>" +
           "<td class=\"labelSide\">" + Lang("Day of Week Average") + "</td>" +
           "<td id=\"calAvgDay1\" class=\"calAvgDay\">&nbsp;</td>" +
           "<td id=\"calAvgDay2\" class=\"calAvgDay\">&nbsp;</td>" +
           "<td id=\"calAvgDay3\" class=\"calAvgDay\">&nbsp;</td>" +
           "<td id=\"calAvgDay4\" class=\"calAvgDay\">&nbsp;</td>" +
           "<td id=\"calAvgDay5\" class=\"calAvgDay\">&nbsp;</td>" +
           "<td id=\"calAvgDay6\" class=\"calAvgDay\">&nbsp;</td>" +
           "<td id=\"calAvgDay0\" class=\"calAvgDay\">&nbsp;</td>" +
           "<td>&nbsp;</td>" +
           "<td colspan=\"2\" id=\"calAvgMonth\" class=\"calAvgDay\">&nbsp;</td>" +
           "</tr>";
  sHTML += "</tbody></table>";

  // apply content
  $("#content").html("<h2>" + Lang(sHeadline) + "</h2>" +
                     DrawSubMenu("thismonth", sSubMenu) +
                     "<div class=\"tableFull\">" + sHTML + "</div>");

  // populate daily values
  for (var iRow in oStatistics.oThisMonth.aData) {
    var oRow = oStatistics.oThisMonth.aData[iRow];
    var iWeekNumber = getWeekNr(oRow.dtDate);
    var iDayNumber = oRow.dtDate.getDay();

    // increment counters
    aWeek[iWeekNumber].iCount++;
    aWeek[iWeekNumber].iTotal += oRow[sDataItem];
    aDay[iDayNumber].iCount++;
    aDay[iDayNumber].iTotal += oRow[sDataItem];
    iTotal += oRow[sDataItem];

    // modify table
    if (sDataItem == "iBW") {
      sHTML = ("<div class=\"date\">" + oRow.dtDate.getDate() + "</div><div class=\"value\">" + DisplayBandwidth(oRow[sDataItem]) + "</div>");
    } else {
      sHTML = ("<div class=\"date\">" + oRow.dtDate.getDate() + "</div><div class=\"value\">" + NumberFormat(oRow[sDataItem], 0) + "</div>");
    }
    $("#calDay" + iDayNumber + "-" + iWeekNumber).html(sHTML).addClass("calDayPopulated");
  }

  // populate week totals
  for (var iIndex = iFirstWeek; iIndex <= iLastWeek; iIndex++) {
    if (aWeek[iIndex].iCount > 0) {
      if (sDataItem == "iBW") {
        $("#calTotWk" + iIndex).html("<div>" + DisplayBandwidth(aWeek[iIndex].iTotal) + "</div>");
        $("#calAvgWk" + iIndex).html("<div>" + DisplayBandwidth(aWeek[iIndex].iTotal / aWeek[iIndex].iCount) + "</div>");
      } else {
        $("#calTotWk" + iIndex).html("<div>" + NumberFormat(aWeek[iIndex].iTotal, 0) + "</div>");
        $("#calAvgWk" + iIndex).html("<div>" + NumberFormat((aWeek[iIndex].iTotal / aWeek[iIndex].iCount), 1) + "</div>");
      }
    }
  }

  // populate day totals
  for (var iIndex = 0; iIndex < 7; iIndex++) {
    if (aDay[iIndex].iCount > 0) {
      if (sDataItem == "iBW") {
        $("#calTotDay" + iIndex).html("<div>" + DisplayBandwidth(aDay[iIndex].iTotal) + "</div>");
        $("#calAvgDay" + iIndex).html("<div>" + DisplayBandwidth(aDay[iIndex].iTotal / aDay[iIndex].iCount) + "</div>");
      } else {
        $("#calTotDay" + iIndex).html("<div>" + NumberFormat(aDay[iIndex].iTotal, 0) + "</div>");
        $("#calAvgDay" + iIndex).html("<div>" + NumberFormat((aDay[iIndex].iTotal / aDay[iIndex].iCount), 1) + "</div>");
      }
    }
  }

  // fill in any remaining empty days
  var dtThisDate = new Date(oRow.dtDate.getFullYear(), oRow.dtDate.getMonth(), (oRow.dtDate.getDate() + 1));
  while (dtThisDate.getMonth() == dtLastDayOfMonth.getMonth()) {
    $("#calDay" + dtThisDate.getDay() + "-" + getWeekNr(dtThisDate)).html("<div class=\"date\">" + dtThisDate.getDate() + "</div>").addClass("calDay");
    dtThisDate.setDate(dtThisDate.getDate() + 1);
  }

  // populate month totals
  if (sDataItem == "iBW") {
    $("#calTotMonth").html("<div><span>" + Lang("Total") + ":</span> " + DisplayBandwidth(iTotal) + "</div>");
    $("#calAvgMonth").html("<div><span>" + Lang("Average") + ":</span> " + DisplayBandwidth(iTotal / oRow.dtDate.getDate()) + "</div>");
  } else {
    $("#calTotMonth").html("<div><span>" + Lang("Total") + ":</span> " + NumberFormat(iTotal, 0) + "</div>");
    $("#calAvgMonth").html("<div><span>" + Lang("Average") + ":</span> " + NumberFormat((iTotal / oRow.dtDate.getDate()), 1) + "</div>");
  }

  // draw graph
  var aGraphItem = [Lang("Monday"), Lang("Tuesday"), Lang("Wednesday"), Lang("Thursday"), Lang("Friday"), Lang("Saturday"), Lang("Sunday")];
  var aGraphValue = [SafeDivide(aDay[1].iTotal, aDay[1].iCount),
                     SafeDivide(aDay[2].iTotal, aDay[2].iCount),
                     SafeDivide(aDay[3].iTotal, aDay[3].iCount),
                     SafeDivide(aDay[4].iTotal, aDay[4].iCount),
                     SafeDivide(aDay[5].iTotal, aDay[5].iCount),
                     SafeDivide(aDay[6].iTotal, aDay[6].iCount),
                     SafeDivide(aDay[0].iTotal, aDay[0].iCount)];

  if (sDataItem == "iBW") 
      for (iIndex in aGraphValue)
	  aGraphValue[iIndex] = SafeDivide(aGraphValue[iIndex], 1024*1024);  

  $("#content").fadeIn(g_iFadeSpeed);
  DrawBar(["","","","","","",""], aGraphValue, aGraphItem);
}

function PageLayout_AllMonths(sPage) {
  var aTable = DrawTable_AllMonths(sPage);
  switch (sPage) {
    case "all":
      var sHTML = "<h2>" + Lang("Emails each Month") + "</h2>" +
                  DrawSubMenu("allmonths", "Emails each Month") +
                  "<div id=\"graph\" class=\"graph\">&nbsp;</div>";
      break;
    case "year":
      var sHTML = "<h2>" + Lang("Emails each Year") + "</h2>" +
                  DrawSubMenu("allmonths", "Emails each Year") +
	         "<div id=\"graph\" class=\"graph\">&nbsp;</div>";
      break;
  }
  sHTML += "<div class=\"tableFull\">" + aTable[1] + "</div>";
  $("#content").html(sHTML);
  $("#content").fadeIn(g_iFadeSpeed);
  if (aTable[0] == true) {
    $(".tablesorter").tablesorter({ headers:{1:{sorter:"commaNumber"},2:{sorter:"commaNumber"},3:{sorter:"commaNumber"},5:{sorter:"commaNumber"},6:{sorter:"commaNumber"},7:{sorter:'bandwidth'}},sortList: [[0,0]],textExtraction:function(node){return node.innerHTML.replace(',', '');}, widgets: ['zebra'] });
  }
  if (sPage == "all") {
    DrawGraph_AllMonths();
  } else {
    DrawGraph_EachYear();
  }
}

function PageLayout_Country(sPage) {
  switch (sPage) {
    case "all":
      var aTable = DrawTable_Country();
      var sHTML = "<h2>" + Lang("Emails by Country") + "</h2>" +
                  DrawSubMenu("country", "Countries") +
                  "<div id=\"pie\" class=\"pie\">&nbsp;</div><div class=\"tablePie\">" +
                  aTable[1] +
                  "</div>";
      $("#content").html(sHTML);
      $("#content").fadeIn(g_iFadeSpeed);
      if (aTable[0] == true) {
        $(".tablesorter").tablesorter( { headers: { 0:{sorter:false},2:{sorter:"commaNumber"},3:{sorter:false},4:{sorter:"commaNumber"},5:{sorter:false},6:{sorter:'bandwidth'},7:{sorter:false} }, sortList: [[2,1]], textExtraction:function(node){return node.innerHTML.replace(',','');}, widgets: ['zebra'] } );
      }
      DrawPie_Country();
      break;
    case "continent":
      var sHTML = "<h2>" + Lang("Visitors by Continent") + "</h2>" +
                  DrawSubMenu("country", "Continents") +
                  "<div id=\"pie\" class=\"pie\">&nbsp;</div><div class=\"tablePie\">" +
                  DrawTable_CountryContinent() +
                  "</div>";
      $("#content").html(sHTML);
      $(".tablesorter").tablesorter( { headers: { 1:{sorter:"commaNumber"}, 2: { sorter: false }, 3:{sorter:"commaNumber"}, 4: { sorter: false },5:{sorter:'bandwidth'}, 6: { sorter: false } }, sortList: [[1,1]], textExtraction: function(node) { return node.innerHTML.replace(',', '');}, widgets: ['zebra'] } );
      $("#content").fadeIn(g_iFadeSpeed);
      DrawPie_CountryContinent();
      break;
    default:
      if (sPage == "Other") {
        var sHTML = "<h2>" + Lang("Other Emails") + "</h2>";
      } else {
        var sHTML = "<h2>" + Lang("Emails from " + sPage) + "</h2>";
      }
      var aTable = DrawTable_Country(sPage);
      sHTML += DrawSubMenu("country", sPage) +
               "<div id=\"pie\" class=\"pie\">&nbsp;</div><div class=\"tablePie\">" +
               aTable[1] + "</div>";
      $("#content").html(sHTML);
      if (aTable[0] == true) {
        $(".tablesorter").tablesorter( { headers: { 0:{sorter:false},2:{sorter:"commaNumber"},3:{sorter:false},4:{sorter:"commaNumber"},5:{sorter:false},6:{sorter:'bandwidth'},7:{sorter:false } }, sortList: [[2,1]], textExtraction: function(node) { return node.innerHTML.replace(',', '');}, widgets: ['zebra'] } );
      }
      $("#content").fadeIn(g_iFadeSpeed);
      DrawPie_Country(sPage);
      break;
  }
}

function PageLayout_EmailHosts(sPage) {
    var aData = oStatistics.oHosts.aData;
    var iPieTotal = oStatistics.oHosts.iTotalEmails;
    var sPieItem = "iEmails";
  var aTable = DrawTable_EmailHost(aData);
  var sHTML = "<h2>" + Lang("Email Hosts") + "</h2>" +
      /*              DrawSubMenu("emails", sSubMenu) + */
              "<div id=\"pie\" class=\"pie\">&nbsp;</div><div class=\"tablePie\">" + aTable[1] + "</div>";
  $("#content").html(sHTML);
  $("#content").fadeIn(g_iFadeSpeed);
  if (aTable[0] == true) {
      //    $(".tablesorter").tablesorter({ headers: { 2: { sorter: false }, 3:{sorter:'bandwidth'}, 4: { sorter: false }, 6: { sorter: false }, 8: { sorter: false } }, sortList: [aSort],textExtraction:function(node){return node.innerHTML.replace(',', '');}, widgets: ['zebra'] });
      $(".tablesorter").tablesorter({widgets: ['zebra'] });
    }
  DrawPie_Emails(aData, iPieTotal, sPieItem);
}

function PageLayout_EmailSenders(sPage) {
    var aData = oStatistics.oSenders.aData;
    var iPieTotal = oStatistics.oSenders.iTotalEmails;
    var sPieItem = "iEmails";
  var aTable = DrawTable_EmailSender(aData);
  var sHTML = "<h2>" + Lang("Email Senders") + "</h2>" +
      /*              DrawSubMenu("emails", sSubMenu) + */
              "<div id=\"pie\" class=\"pie\">&nbsp;</div><div class=\"tablePie\">" + aTable[1] + "</div>";
  $("#content").fadeIn(g_iFadeSpeed);
  $("#content").html(sHTML);
  if (aTable[0] == true) {
      //    $(".tablesorter").tablesorter({ headers: { 2: { sorter: false }, 3:{sorter:'bandwidth'}, 4: { sorter: false }, 6: { sorter: false }, 8: { sorter: false } }, sortList: [aSort],textExtraction:function(node){return node.innerHTML.replace(',', '');}, widgets: ['zebra'] });
      $(".tablesorter").tablesorter({widgets: ['zebra'] });
  }
  DrawPie_Emails(aData, iPieTotal, sPieItem);
}

function PageLayout_EmailRecipients(sPage) {
    var aData = oStatistics.oRecipients.aData;
    var iPieTotal = oStatistics.oRecipients.iTotalEmails;
    var sPieItem = "iEmails";
  var aTable = DrawTable_EmailRecipient(aData);
  var sHTML = "<h2>" + Lang("Email Recipients") + "</h2>" +
      /*              DrawSubMenu("emails", sSubMenu) + */
              "<div id=\"pie\" class=\"pie\">&nbsp;</div><div class=\"tablePie\">" + aTable[1] + "</div>";
  $("#content").html(sHTML);
  $("#content").fadeIn(g_iFadeSpeed);
  if (aTable[0] == true) {
      //    $(".tablesorter").tablesorter({ headers: { 2: { sorter: false }, 3:{sorter:'bandwidth'}, 4: { sorter: false }, 6: { sorter: false }, 8: { sorter: false } }, sortList: [aSort],textExtraction:function(node){return node.innerHTML.replace(',', '');}, widgets: ['zebra'] });
      $(".tablesorter").tablesorter({widgets: ['zebra'] });
    }
  DrawPie_Emails(aData, iPieTotal, sPieItem);
}


function PageLayout_Status(sPage) {
  switch (sPage) {
      /*    case "404":
      var aTable = DrawTable_Status404();
      var sHTML = "<h2>" + Lang("SMTP Status Codes") + ": 404s</h2>" +
                  DrawSubMenu("status", "File Not Found URLs") +
                  "<div id=\"pie\" class=\"pie\">&nbsp;</div><div class=\"tablePie\">" + aTable[1] + "</div>";
      $("#content").html(sHTML);
      if (aTable[0] == true) {
        $(".tablesorter").tablesorter({ headers: { 1: { sorter: "commaNumber" } }, sortList: [[1,1]],textExtraction:function(node){return node.innerHTML.replace(',', '');}, widgets: ['zebra'] });
      }
      $("#content").fadeIn(g_iFadeSpeed);
      DrawPie_Status404(sPage);
      break;*/
    default:
      var aTable = DrawTable_Status();
      var sHTML = "<h2>" + Lang("SMTP Status Codes") + "</h2>" +
                  DrawSubMenu("status", "Status Codes") +
                  "<div id=\"pie\" class=\"pie\">&nbsp;</div><div class=\"tablePie\">" + aTable[1] + "</div>";
      $("#content").html(sHTML);
      $("#content").fadeIn(g_iFadeSpeed);
      if (aTable[0] == true) {
	  //        $(".tablesorter").tablesorter({ headers: { 2: { sorter: "commaNumber" }, 3:{ sorter: false }, 4: { sorter: "bandwidth" }, 5: { sorter: false } }, sortList: [[2,1]],textExtraction:function(node){return node.innerHTML.replace(',', '');}, widgets: ['zebra'] });
	  $(".tablesorter").tablesorter({widgets: ['zebra'] });	  
      }
      DrawPie_Status(sPage);
  }
}

function PageLayout_ThisMonth(sPage) {
  switch (sPage) {
    case "all":
      var aTable = DrawTable_ThisMonth();
      var sHTML = "<h2>" + Lang("Emails this Month") + "</h2>" +
                  DrawSubMenu("thismonth", "Overview") +
                  "<div id=\"graph\" class=\"graph\">&nbsp;</div><div class=\"tableFull\">" + aTable[1] + "</div>";
      $("#content").html(sHTML);
      $("#content").fadeIn(g_iFadeSpeed);
      if (aTable[0] == true) {
        $(".tablesorter").tablesorter({ headers:{ 2:{sorter:"commaNumber"},3:{sorter:"commaNumber"},5:{sorter:"commaNumber"},7:{sorter:"bandwidth"},8:{sorter:"bandwidth"}},sortList:[[1,0]],textExtraction:function(node){return node.innerHTML.replace(',', '');}, widgets: ['zebra'] });
      }
      DrawGraph_ThisMonth();
      break;
    case "emails":
      Misc_ThisMonthCalendar("Calendar of Emails this Month", "Calendar of Emails", "iPages");
      break;
    case "bandwidth":
      Misc_ThisMonthCalendar("Calendar of Bandwidth Usage this Month", "Calendar of Bandwidth Usage", "iBW");
      break;
  }
}

function PageLayout_Time(sPage) {
  var aTable = DrawTable_Time(sPage);
  var sHTML = "<h2>" + Lang("Emails over 24 Hours") + "</h2>" +
              "<div id=\"graph\" class=\"graph\">&nbsp;</div>" +
              "<div class=\"tableFull\">" + aTable[1] + "</div>";
  $("#content").html(sHTML);
  $("#content").fadeIn(g_iFadeSpeed);
  if (aTable[0] == true) {
    $(".tablesorter").tablesorter({ headers:{1:{sorter:"commaNumber"},2:{sorter:false},3:{sorter:false},4:{sorter:"commaNumber"},5:{sorter:false},6:{sorter:false},7:{sorter:'bandwidth'},8:{sorter:false},9:{sorter:false},10:{sorter:"commaNumber"},11:{sorter:"commaNumber"},12:{sorter:'bandwidth'}},sortList: [[0,0]],textExtraction:function(node){return node.innerHTML.replace(',', '');}, widgets: ['zebra'] });
  }
  DrawGraph_Time();
}

function PagingInputNumber(oEvent, oInput, sType) {
  var iCode = (oEvent.charCode || oEvent.keyCode);
  if (iCode == 13) {
    var iValue = parseFloat($(oInput).val());
    if (isNaN(iValue) == true) { return false; }
    if (iValue < 1) { return false; }
    if (iValue != Math.round(iValue)) { return false; }
    switch (sType) {
      case "keyphrases":
        if (iValue > (Math.floor((oStatistics.oKeyphrases.aData.length - 1) / oPaging.oKeyphrases.iRowsPerPage) + 1)) { return false; }
        RedrawTable_Keyphrases("iCurrPage", (iValue - 1));
        break;
      case "keywords":
        if (iValue > (Math.floor((oStatistics.oKeywords.aData.length - 1) / oPaging.oKeywords.iRowsPerPage) + 1)) { return false; }
        RedrawTable_Keywords("iCurrPage", (iValue - 1));
        break;
    }
  }
  if ((iCode == 8) || (iCode == 9) || ((iCode > 34) && (iCode < 38)) || (iCode == 39) || (iCode == 46) || ((iCode > 47) && (iCode < 58))) {
    return true;
  } else {
    return false;
  }
}

function Paging_Keyphrases() {
  // get values
  iTotalFreq = oStatistics.oKeyphrases.iTotalFreq;
  switch (oPaging.oKeyphrases.sSort) {
    case "freqASC":
      var sKeyphraseClass = "";
      var sFrequencyClass = " headerSortDown";
      var sKeyphraseSort = "wordDESC";
      var sFrequencySort = "freqDESC";
      var aData = oStatistics.oKeyphrases.aData;
      var iDisplayOrder = -1;
      break;
    case "freqDESC":
      var sKeyphraseClass = "";
      var sFrequencyClass = " headerSortUp";
      var sKeyphraseSort = "wordDESC";
      var sFrequencySort = "freqASC";
      var aData = oStatistics.oKeyphrases.aData;
      var iDisplayOrder = 1;
      break;
    case "wordASC":
      var sKeyphraseClass = " headerSortDown";
      var sFrequencyClass = "";
      var sKeyphraseSort = "wordDESC";
      var sFrequencySort = "freqDESC";
      var aData = oStatistics.oKeyphrasesAlphabetical.aData;
      var iDisplayOrder = -1;
      break;
    case "wordDESC":
      var sKeyphraseClass = " headerSortUp";
      var sFrequencyClass = "";
      var sKeyphraseSort = "wordASC";
      var sFrequencySort = "freqDESC";
      var aData = oStatistics.oKeyphrasesAlphabetical.aData;
      var iDisplayOrder = 1;
      break;
  }

  // create header
  var sDesc = (Lang("Showing [START] to [END] of [TOTAL] keyphrases")).replace("[TOTAL]", aData.length);
  var sHTML = "<table class=\"tablesorter\" cellspacing=\"0\">\n" +
              "<thead><tr>" +
              "<th class=\"header" + sKeyphraseClass + "\" onclick=\"RedrawTable_Keyphrases('sSort', '" + sKeyphraseSort + "')\" width=\"80%\">" + Lang("Keyphrase") + "</th>" +
              "<th class=\"header" + sFrequencyClass + "\" onclick=\"RedrawTable_Keyphrases('sSort', '" + sFrequencySort + "')\" width=\"10%\">" + Lang("Frequency") + "</th>" +
              "<th class=\"noborder\" width=\"10%\">&nbsp;</th>" +
              "</tr></thead>\n" +
              "<tbody>";

  // create table body
  aHTML = new Array();
  if (iDisplayOrder == 1) {
    var iStart = (oPaging.oKeyphrases.iCurrPage * oPaging.oKeyphrases.iRowsPerPage);
    var iEnd = (iStart + oPaging.oKeyphrases.iRowsPerPage);
    if (iEnd > aData.length) {
      iEnd = aData.length;
    }
    sDesc = sDesc.replace("[START]", iStart + 1).replace("[END]", iEnd);
    for (var i = iStart; i < iEnd; i++) {
      aHTML.push(((i % 2 == 0) ? "<tr>" : "<tr class=\"odd\">") +
                 "<td>" + aData[i].sPhrase + "</td>" +
                 "<td class=\"right\">" + NumberFormat(aData[i].iFreq, 0) + "</td>" +
  			         "<td class=\"noborder right\">" + ((aData[i].iFreq / iTotalFreq) * 100).toFixed(1) + "%</td>" +
                 "</tr>\n");
    }
  } else {
    if (aData.length > 0) {
      var iStart = (aData.length - 1) - (oPaging.oKeyphrases.iCurrPage * oPaging.oKeyphrases.iRowsPerPage);
      var iEnd = (iStart - oPaging.oKeyphrases.iRowsPerPage);
      if (iEnd < -1) {
        iEnd = -1;
      }
      sDesc = sDesc.replace("[START]", iStart + 1).replace("[END]", iEnd + 2);
      for (var i = iStart; i > iEnd; i--) {
        aHTML.push(((i % 2 == 0) ? "<tr>" : "<tr class=\"odd\">") +
                   "<td>" + aData[i].sPhrase + "</td>" +
                   "<td class=\"right\">" + NumberFormat(aData[i].iFreq, 0) + "</td>" +
    			         "<td class=\"noborder right\">" + ((aData[i].iFreq / iTotalFreq) * 100).toFixed(1) + "%</td>" +
                   "</tr>\n");
      }
    }
  }

  // output
  if (aHTML.length > 0) {
    var iMaxPage = Math.floor((aData.length - 1) / oPaging.oKeyphrases.iRowsPerPage);
    var sNavigation = "<div id=\"paging\"><span>" + sDesc + "</span>";
    if (oPaging.oKeyphrases.iCurrPage > 0) {
      sNavigation += "<img src=\"themes/" + sThemeDir + "/paging/first.gif\" onmouseover=\"this.src='themes/" + sThemeDir + "/paging/first_on.gif'\" onmouseout=\"this.src='themes/" + sThemeDir + "/paging/first.gif'\" style=\"cursor: pointer;\" onclick=\"RedrawTable_Keyphrases('iCurrPage', 0)\" />" +
                     "<img src=\"themes/" + sThemeDir + "/paging/prev.gif\" onmouseover=\"this.src='themes/" + sThemeDir + "/paging/prev_on.gif'\" onmouseout=\"this.src='themes/" + sThemeDir + "/paging/prev.gif'\" style=\"cursor: pointer;\" onclick=\"RedrawTable_Keyphrases('iCurrPage', " + (oPaging.oKeyphrases.iCurrPage - 1) + ")\" />";
    } else {
      sNavigation += "<img src=\"themes/" + sThemeDir + "/paging/first_off.gif\" />" +
                     "<img src=\"themes/" + sThemeDir + "/paging/prev_off.gif\" />";
    }
    sNavigation += "<span><input type=\"text\" value=\"" + (oPaging.oKeyphrases.iCurrPage + 1) + "\" onkeypress=\"return PagingInputNumber(event, this, 'keyphrases');\" />" + " / " + (iMaxPage + 1) + "</span>";
    if (oPaging.oKeyphrases.iCurrPage < iMaxPage) {
      sNavigation += "<img src=\"themes/" + sThemeDir + "/paging/next.gif\" onmouseover=\"this.src='themes/" + sThemeDir + "/paging/next_on.gif'\" onmouseout=\"this.src='themes/" + sThemeDir + "/paging/next.gif'\" style=\"cursor: pointer;\" onclick=\"RedrawTable_Keyphrases('iCurrPage', " + (oPaging.oKeyphrases.iCurrPage + 1) + ")\" />" +
                     "<img src=\"themes/" + sThemeDir + "/paging/last.gif\" onmouseover=\"this.src='themes/" + sThemeDir + "/paging/last_on.gif'\" onmouseout=\"this.src='themes/" + sThemeDir + "/paging/last.gif'\" style=\"cursor: pointer;\" onclick=\"RedrawTable_Keyphrases('iCurrPage', " + iMaxPage + ")\" />";
    } else {
      sNavigation += "<img src=\"themes/" + sThemeDir + "/paging/next_off.gif\" />" +
                     "<img src=\"themes/" + sThemeDir + "/paging/last_off.gif\" />";
    }
    sNavigation += "</div>";
    return (sHTML + aHTML.join("\n") + "</tbody></table>" + sNavigation);
  } else {
    return (sHTML + "<tr><td class=\"center\" colspan=\"3\">" + Lang("There is no data to display") + "</td></tr></tbody></table>");
  }
}

function PopulateData_AllMonths(sPage) {
  $("#loading").show();

	// create data objects
	var oAM = { "aData":[], "aYearDayCount":[] };

  $.ajax({
    type: "GET",
    url: XMLURL("ALLMONTHS"),
    success: function(oXML){
      // CheckLastUpdate(oXML); disabled until update problem is fixed. only affects this call.

      var aTemp = [];
      var iCurrentYear = 0;
      $(oXML).find('month').each(function() {
        dtTemp = new Date(parseInt($(this).attr("year")), (parseInt($(this).attr("month")) - 1), 1);

        // days in month
        iDaysInMonth = parseFloat($(this).attr("daysinmonth"));

        // push items onto array
        aTemp.push({ "dtDate"       : new Date(dtTemp.getFullYear(), dtTemp.getMonth(), 1),
                     "iMonth"       : $(this).attr("month"),
                     "iYear"        : $(this).attr("year"),
                     "iDaysInMonth" : iDaysInMonth,
            	 		   "iVisits"      : $(this).attr("visits"),
            	 		   "iUniques"     : $(this).attr("uniques"),
            			   "iPages"       : $(this).attr("pages"),
            			   "iHits"        : $(this).attr("hits"),
                     "iBW"          : $(this).attr("bw"),
                     "iDaysInMonth" : iDaysInMonth
                  });

        // count days in year
        if (iCurrentYear != dtTemp.getFullYear()) {
          iCurrentYear = dtTemp.getFullYear();
          oAM.aYearDayCount[iCurrentYear] = iDaysInMonth;
        } else {
          oAM.aYearDayCount[iCurrentYear] += iDaysInMonth;
        }
      });

      // apply data
      oAM.aData = aTemp;
      oStatistics.oAllMonths = oAM;
      $("#loading").hide();
      DrawPage(sPage);
    }
  });
}

function PopulateData_Country(sPage) {
  $("#loading").show();

	// create data objects
	var oC = { "bPopulated":false, "iTotalPages":0, "iTotalHits":0, "iTotalBW":0, "aData":[] };
	oC.oContinent = { "Africa":{}, "Antartica":{}, "Asia":{}, "Europe":{}, "North America":{}, "Oceania":{}, "South America":{}, "Other":{} };
	for (var sContinent in oC.oContinent) {
		oC.oContinent[sContinent] = { "iTotalPages":0, "iTotalHits":0, "iTotalBW":0 };
	}

  $.ajax({
    type: "GET",
    url: XMLURL("DOMAIN"),
    success: function(oXML){
      CheckLastUpdate(oXML);

      $(oXML).find('item').each(function() {
        // collect values
        var sCountryCode = $(this).attr("id");
        var sCountryName = gc_aCountryName[sCountryCode];
        if (typeof gc_aCountryName[sCountryCode] == "undefined") {
          sCountryName = ("Unknown (code: " + sCountryCode.toUpperCase() + ")");
        }
        var sContinent   = gc_aCountryContinent[sCountryCode];
        if (typeof gc_aContinents[sContinent] == "undefined") {
          sContinent = "Other";
        }
        var iPages       = parseInt($(this).attr("pages"));
        var iHits        = parseInt($(this).attr("hits"));
        var iBW          = parseInt($(this).attr("bw"));

        // increment totals
        oC.iTotalPages += iPages;
        oC.iTotalHits += iHits;
        oC.iTotalBW += iBW;
        oC.oContinent[sContinent].iTotalPages += iPages;
        oC.oContinent[sContinent].iTotalHits += iHits;
        oC.oContinent[sContinent].iTotalBW += iBW;

        // populate array
        oC.aData.push({ "sCountryCode":sCountryCode,
                        "sCountryName":sCountryName,
                        "sContinent":sContinent,
                        "iPages":iPages,
                        "iHits":iHits,
                        "iBW":iBW } );
      });

      // apply data
      oC.aData.sort(Sort_Pages);
      oStatistics.oCountry = oC;
      $("#loading").hide();
      DrawPage(sPage);
    }
  });
}

function PopulateData_Status(sPage) {
  $("#loading").show();

	// create data objects
	var oS = { "iTotalHits":0, "iTotalBW":0, "aData":[] };

  $.ajax({
    type: "GET",
    url: XMLURL("ERRORS"),
    success: function(oXML){
      CheckLastUpdate(oXML);

      $(oXML).find('item').each(function() {
        // collect values
        var sCode        = $(this).attr("id");
        var sDescription = gc_aSMTPStatus[sCode];
        if (typeof gc_aSMTPStatus[sCode] == "undefined") {
          sDescription = "&nbsp;";
        }
        var iHits        = parseInt($(this).attr("hits"));
        var iBW          = parseInt($(this).attr("bw"));

        // increment totals
        oS.iTotalHits += iHits;
        oS.iTotalBW += iBW;

        // populate array
        oS.aData.push({ "sCode":sCode,
                        "sDescription":sDescription,
                        "iHits":iHits,
                        "iBW":iBW } );
      });

      // apply data
      oS.aData.sort(Sort_Hits);
      oStatistics.oStatus = oS;
      $("#loading").hide();
      DrawPage(sPage);
    }
  });
}

function PopulateData_Status404(sPage) {
  $("#loading").show();

	// create data objects
	var oS = { "iTotalHits":0, "aData":[] };

  $.ajax({
    type: "GET",
    url: XMLURL("SIDER_404"),
    success: function(oXML){
      CheckLastUpdate(oXML);

      $(oXML).find('item').each(function() {
        // collect values
        var sURL         = $(this).attr("url");
        var iHits        = parseInt($(this).attr("hits"));
        var sReferrer    = $(this).attr("referrer");

        // increment totals
        oS.iTotalHits += iHits;

        // populate array
        oS.aData.push({ "sURL":sURL.split("/").join("&#8203;/").split("-").join("-&#8203;").split("_").join("_&#8203;"),
                        "iHits":iHits,
                        "sReferrer":sReferrer,
                        "sReferrerVisible":sReferrer.split("/").join("&#8203;/").split("-").join("-&#8203;").split("_").join("_&#8203;") } );
      });

      // apply data
      oS.aData.sort(Sort_Hits);
      oStatistics.oStatus404 = oS;
      $("#loading").hide();
      DrawPage(sPage);
    }
  });
}

function PopulateData_Hosts(sPage) {
 $("#loading").show();

	// create data objects
	var oTM = { "iTotalEmails":0,  "iTotalBW":0,  "aData":[] };

  $.ajax({
    type: "GET",
    url: XMLURL("VISITOR"),
    success: function(oXML){
      CheckLastUpdate(oXML);

      var aTemp1 = [];
      var iMaxDate = 0;
      var iTotalEmails = 0;
      var iTotalBW = 0;
      $(oXML).find('item').each(function() {
        // collect values
        var sAddress        = $(this).attr("address");
        var iEmails      = parseInt($(this).attr("pages"));
        var iBW          = parseInt($(this).attr("bw"));
	var sLastVisit   = $(this).attr("lastvisit");


        // create javascript date
	/*        dtDate = new Date(sDate.substr(0,4),
                          (parseInt(StripLeadingZeroes(sDate.substr(4,2))) - 1),
                          sDate.substr(6,2));*/

        // populate array
        aTemp1.push({ "sAddress"   : sAddress,
                      "iEmails"  : iEmails,
                      "iBW"      : iBW } );
        //dtMaxDate = dtDate;
	iTotalEmails += iEmails;
	iTotalBW += iBW;
	  });
      oTM.aData = aTemp1;
      oTM.iTotalEmails = iTotalEmails;
      oTM.iTotalBW =  iTotalBW;
      oStatistics.oHosts = oTM;
      $("#loading").hide();
      DrawPage(sPage);      	  
	  }});
}

function PopulateData_Senders(sPage) {
 $("#loading").show();

	// create data objects
	var oTM = { "iTotalEmails":0,  "iTotalBW":0,  "aData":[] };

  $.ajax({
    type: "GET",
    url: XMLURL("EMAILSENDER"),
    success: function(oXML){
      CheckLastUpdate(oXML);

      var aTemp1 = [];
      var iMaxDate = 0;
      var iTotalEmails = 0;
      var iTotalBW = 0;
      $(oXML).find('item').each(function() {
        // collect values
        var sAddress        = $(this).attr("address");
        var iEmails      = parseInt($(this).attr("emails"));
        var iBW          = parseInt($(this).attr("bw"));
	var sLastVisit   = $(this).attr("lastvisit");


        // create javascript date
	/*        dtDate = new Date(sDate.substr(0,4),
                          (parseInt(StripLeadingZeroes(sDate.substr(4,2))) - 1),
                          sDate.substr(6,2));*/

        // populate array
        aTemp1.push({ "sAddress"   : sAddress,
                      "iEmails"  : iEmails,
                      "iBW"      : iBW } );
        //dtMaxDate = dtDate;
	iTotalEmails += iEmails;
	iTotalBW += iBW;
	  });
      oTM.aData = aTemp1;
      oTM.iTotalEmails = iTotalEmails;
      oTM.iTotalBW =  iTotalBW;
      oStatistics.oSenders = oTM;
      $("#loading").hide();
      DrawPage(sPage);      	  
	  }});
}

function PopulateData_Recipients(sPage) {
 $("#loading").show();

	// create data objects
	var oTM = { "iTotalEmails":0,  "iTotalBW":0,  "aData":[] };

  $.ajax({
    type: "GET",
    url: XMLURL("EMAILRECEIVER"),
    success: function(oXML){
      CheckLastUpdate(oXML);

      var aTemp1 = [];
      var iMaxDate = 0;
      var iTotalEmails = 0;
      var iTotalBW = 0;
      $(oXML).find('item').each(function() {
        // collect values
        var sAddress        = $(this).attr("address");
        var iEmails      = parseInt($(this).attr("emails"));
        var iBW          = parseInt($(this).attr("bw"));
	var sLastVisit   = $(this).attr("lastvisit");


        // create javascript date
	/*        dtDate = new Date(sDate.substr(0,4),
                          (parseInt(StripLeadingZeroes(sDate.substr(4,2))) - 1),
                          sDate.substr(6,2));*/

        // populate array
        aTemp1.push({ "sAddress"   : sAddress,
                      "iEmails"  : iEmails,
                      "iBW"      : iBW } );
        //dtMaxDate = dtDate;
	iTotalEmails += iEmails;
	iTotalBW += iBW;
	  });
      oTM.aData = aTemp1;
      oTM.iTotalEmails = iTotalEmails;
      oTM.iTotalBW =  iTotalBW;
      oStatistics.oRecipients = oTM;
      $("#loading").hide();
      DrawPage(sPage);      	  
	  }});
}

function PopulateData_ThisMonth(sPage) {
  $("#loading").show();

	// create data objects
	var oTM = { "iTotalPages":0, "iTotalHits":0, "iTotalBW":0, "iTotalVisits":0, "aData":[] };

  $.ajax({
    type: "GET",
    url: XMLURL("DAY"),
    success: function(oXML){
      CheckLastUpdate(oXML);

      var aTemp1 = [];
      var iMaxDate = 0;
      $(oXML).find('item').each(function() {
        // collect values
        var sDate        = $(this).attr("date");
        var iVisits      = parseInt($(this).attr("visits"));
    		var iPages       = parseInt($(this).attr("pages"));
    		var iHits        = parseInt($(this).attr("hits"));
        var iBW          = parseInt($(this).attr("bw"));

        // increment totals
        oTM.iTotalVisits += iVisits;
    		oTM.iTotalPages += iPages;
    		oTM.iTotalHits += iHits;
        oTM.iTotalBW += iBW;

        // create javascript date
        dtDate = new Date(sDate.substr(0,4),
                          (parseInt(StripLeadingZeroes(sDate.substr(4,2))) - 1),
                          sDate.substr(6,2));

        // populate array
        aTemp1.push({ "dtDate"   : dtDate,
                      "iVisits"  : iVisits,
            				  "iPages"   : iPages,
            				  "iHits"    : iHits,
                      "iBW"      : iBW } );
        dtMaxDate = dtDate;
      });

      // populate complete array (including empty values)
      var aTemp2 = [];
      var iPointer = 0;
      for (var iIndex = 0; iIndex < dtMaxDate.getDate(); iIndex++) {
        dtExpectedDate = new Date(dtMaxDate.getFullYear(), dtMaxDate.getMonth(), (iIndex + 1));
        if (aTemp1[iPointer].dtDate.valueOf() == dtExpectedDate.valueOf()) {
          aTemp2.push({ "dtDate"  : new Date(dtMaxDate.getFullYear(), dtMaxDate.getMonth(), (iIndex + 1)),
                        "iVisits" : aTemp1[iPointer].iVisits,
              				  "iPages"  : aTemp1[iPointer].iPages,
              				  "iHits"   : aTemp1[iPointer].iHits,
                        "iBW"     : aTemp1[iPointer].iBW } );
          iPointer++;
        } else {
          aTemp2.push({ "dtDate"  : new Date(dtMaxDate.getFullYear(), dtMaxDate.getMonth(), (iIndex + 1)),
                        "iVisits" : 0,
              				  "iPages"  : 0,
              				  "iHits"   : 0,
                        "iBW"     : 0 } );
        }
      }

      // apply data
      oTM.aData = aTemp2;
      oStatistics.oThisMonth = oTM;
      $("#loading").hide();
      DrawPage(sPage);
    }
  });
}

function PopulateData_Time(sPage) {
  $("#loading").show();

	// create data objects
	var oT = { "iTotalPages":0, "iTotalHits":0, "iTotalBW":0, "iTotalNVPages":0, "iTotalNVHits":0, "iTotalNVBW":0, "aData":[]  };

  $.ajax({
    type: "GET",
    url: XMLURL("TIME"),
    success: function(oXML){
      CheckLastUpdate(oXML);

      var aTemp = [];
      $(oXML).find('item').each(function() {
        // collect values
        var iHour        = parseInt($(this).attr("hour"));
        var iPages       = parseInt($(this).attr("pages"));
        var iHits        = parseInt($(this).attr("hits"));
        var iBW          = parseInt($(this).attr("bw"));
        var iNVPages     = parseInt($(this).attr("notviewedpages"));
        var iNVHits      = parseInt($(this).attr("notviewedhits"));
        var iNVBW        = parseInt($(this).attr("notviewedbw"));

        // increment totals
        oT.iTotalPages += iPages;
        oT.iTotalHits += iHits;
        oT.iTotalBW += iBW;
        oT.iTotalNVPages += iPages;
        oT.iTotalNVHits += iHits;
        oT.iTotalNVBW += iBW;

        // populate array
        oT.aData.push({ "iHour":iHour,
                        "iPages":iPages,
                        "iHits":iHits,
                        "iBW":iBW,
                        "iNVPages":iNVPages,
                        "iNVHits":iNVHits,
                        "iNVBW":iNVBW } );
      });

      // apply data
      oStatistics.oTime = oT;
      $("#loading").hide();
      DrawPage(sPage);
    }
  });
}


function RedrawTable_Keywords(sParam, sValue) {
  oPaging.oKeywords[sParam] = sValue;
  $(".tablePie").html(Paging_Keywords());
}

function SafeDivide(iFirst, iSecond) {
  if (iSecond != 0) {
    return (iFirst / iSecond);
  } else {
    return 0;
  }
}

function ShowTools(sID) {
  if (arguments.length > 0) {
    sToolID = sID;
  }

  // loop through items
  if ($("#tools .tool:visible").size() > 0) {
    $("#tools .tool:visible").each(function() {
      if ($(this).attr("id") == sToolID) {
        $(this).stop().slideUp(350);
      } else {
        $(this).stop().slideUp(350, ShowTools);
      }
    });
  } else {
    $("#" + sToolID).stop().slideDown(350);
  }
}

function Sort_Freq(a, b) {
  return b.iFreq - a.iFreq;
}

function Sort_Hits(a, b) {
  return b.iHits - a.iHits;
}

function Sort_Pages(a, b) {
  return b.iPages - a.iPages;
}

function Sort_Phrase(a, b) {
  return ((a.sPhrase < b.sPhrase) ? -1 : ((a.sPhrase > b.sPhrase) ? 1 : 0));
}

function Sort_Word(a, b) {
  return ((a.sWord < b.sWord) ? -1 : ((a.sWord > b.sWord) ? 1 : 0));
}

function UpdateSite() {
  $("#loading").show();
  $.ajax({
    type: "POST",
    url: sUpdateFilename,
    data: ("config=" + g_sConfig + "&pass=" + MD5($("#password").val())),
    success: function(oXML) {
      switch ($(oXML).find('result:eq(0)').attr("type")) {
        case "bad_password":
          $("#loading").hide();
          alert( Lang("The password you entered was incorrect.") );
          break;
        case "updated":
          var sURL = "?config=" + g_sConfig + "&year=" + g_iYear + "&month=" + g_iMonth + "&view=" + g_sCurrentView + "&lang=" + g_sLanguage;
          self.location.href = sURL;
          break;
        default:
          $("#loading").hide();
      }
    }
  });
}

function UpdateSiteKeyUp(event) {
  if (event.keyCode == 13) {
    UpdateSite();
  }
}

function XMLURL(sPage) {
  var sURL = "";
  if (g_bUseStaticXML == true) {
    switch (sPage) {
      case "ALLMONTHS":
        sURL = ("static/jawstats." + g_sConfig + ".allmonths.xml?cache=" + g_dtLastUpdate);
        break;
      default:
        if (g_iMonth < 10) {
          sURL = ("static/jawstats" + g_iYear + "0" + g_iMonth + "." + g_sConfig + "." + sPage.toLowerCase() + ".xml?cache=" + g_dtLastUpdate);
        } else {
          sURL = ("static/jawstats" + g_iYear + g_iMonth + "." + g_sConfig + "." + sPage.toLowerCase() + ".xml?cache=" + g_dtLastUpdate);
        }
    }
  } else {
    switch (sPage) {
      case "ALLMONTHS":
        sURL = ("xml_history.php?config=" + g_sConfig);
        break;
      case "PAGES":
        sURL = ("xml_pages.php?config=" + g_sConfig + "&year=" + g_iYear + "&month=" + g_iMonth);
        break;
      default:
        sURL = ("xml_stats.php?config=" + g_sConfig + "&section=" + sPage + "&year=" + g_iYear + "&month=" + g_iMonth);
    }
  }
  return sURL;
}
