//Copyright 2000. Compendium Research Corporation. All Rights Reserved.

var bDebug = 1;        // change to 1 for extra output
var sNl = "\r";
var sOut = "", sDump = "";         // html output string
var nErrorNumber = -1.2345e-12;

var sSub = "%s";

var shStart = "<html>" + sNl
      + "<head><title>%s</title>" + sNl
      + "<link rel='stylesheet' href='normal.css'>" + sNl
      + "</head>" + sNl
      + "<body>" + sNl
      + "<BASEFONT FACE='Arial, Helvetica, sans-serif'>";

var shHeading1 =  "<TABLE border=0 cellpadding=0 "
                + "cellspacing=0 width=500>" + sNl
      + "<TR><TD><br>"
      + "<font size=6><b>%s</b></font></TD></TR></TABLE><br>";

var shHeadGif = "<TABLE width=500 cellpadding=0 cellspacing=0>" + sNl
      + "<TR><TD><img src='%s' " + sNl
      + "width=471 height=24></TD></TR></TABLE>";

var shHeading2 =  "<TABLE border=0 cellpadding=0 "
                + "cellspacing=0 width=500>" + sNl
      + "<TR><TD>"
      + "<font size=+2><b>%s</b></font></TD></TR></TABLE>";

var shBeginTable1 =
      "<TABLE width=500 border=1 cellpadding=3 cellspacing=0><BR><BR>";
var shBeginTable2 =
      "<TABLE border=0 cellpadding=0 cellspacing=0 width=500><BR>";

var shEndTable = "</table>";

var shBeginRow1 = "<tr>";
var shBeginRow2 = "<tr align=center>";
var shEndRow = "</tr>";

var shCell1 = "<TD colSpan=5><font size=-1><B>%s"
		+ "</B></font></TD></TR>";

var shCell1 = "<TD class='tdData'>%s</TD>";
var shCell2 = "<TD class='tdDataRight'>%s</TD>";
var shEndPage = "<p><a href='javascript: history.go(-1)'>Back</a>"

function EmitRow1(s1, s2)
{
   Emit(shBeginRow1);
   Emit1(shCell1, s1);
   Emit1(shCell2, s2);
   Emit(shEndRow);
}

var shLongText = ""

   + "<TR><TD>Your <B>total monthly lender" + sNl
   + "payment</B> includes monthly mortgage principal and" + sNl
   + "interest plus monthly property tax and home insurance" + sNl
   + "costs (also known as \"PITI\").</TD></TR>" + sNl + sNl

   + "<TR><TD><BR>Your <B>total monthly debt" + sNl
   + "payment</B> includes monthly mortgage principal and" + sNl
   + "interest plus monthly property tax and home insurance" + sNl
   + "costs, PLUS any other debt payments you must pay every" + sNl
   + "month.</TD></TR>" + sNl + sNl

   + "<TR><TD><BR>A <B>monthly PMI payment</B>" + sNl
   + "appears above if your down payment is less than 20% of" + sNl
   + "your home value. That means you must pay an extra .7%" + sNl
   + "of your beginning loan balance per year for private" + sNl
   + "mortgage insurance (\"PMI\").  In many cases, the lender" + sNl
   + "will allow cancellation of PMI when the loan is paid" + sNl
   + "down to 80% of the original property" + sNl
   + "value.</TD></TR>" + sNl + sNl

   + "<TR><TD><BR>The <B>28% Qualifying Annual" + sNl
   + "Income</B> is the amount that you need to earn to meet" + sNl
   + "the housing expense guideline used by lenders to" + sNl
   + "determine the mortgage amount they will lend to a home" + sNl
   + "buyer.  Lenders generally say that the <b>total monthly lender" + sNl
   + "payment</b> plus the <b>total monthly PMI payment</b> (if applicable)" + sNl
   + "should not exceed 28 percent of the homeowner's gross monthly" + sNl
   + "income.</TD></TR>" + sNl + sNl

   + "<TR><TD><BR>The <B>36% Qualifying Annual" + sNl
   + "Income</B> is the amount that you need to earn to meet" + sNl
   + "the long term debt guideline used by lenders to" + sNl
   + "determine the mortgage amount they will lend to a home" + sNl
   + "buyer.  Lenders generally say that the <b>total monthly debt" + sNl
   + "payment</b> plus the <b>total monthly PMI payment</b> (if applicable)" + sNl
   + "should not exceed 36 percent of the homeowner's gross monthly" + sNl
   + "income.</TD></TR>" + sNl + sNl

   + "<TR><TD><BR>As long as your total gross" + sNl
   + "annual income (salary plus interest, rental and" + sNl
   + "dividend income) meets <B>BOTH</B> the 28% Qualifying" + sNl
   + "Annual Income and the 36% Qualifying Annual Income," + sNl
   + "you will likely qualify.</TD></TR>" + sNl + sNl;

function Initialize(oForm)
{
    if (0 && bDebug)
    {
	oForm.appn0001.value = 800;
	oForm.appn0002.value = 1616;
	oForm.appn0003.value = 1000;
	oForm.appn0004.value = 1000;
	oForm.appn0005.value = 100000;
	oForm.appn0006.value = 20000;
    }
}

function Execute(oForm)
{
   var iError = 0;
   var nPayment, nAnnualTax, nAnnualInsurance, nMonthlyDebt;
   var nSalePrice, nDownPayment;
   var nPrincipal, nInputInterest, iYears;

   var nLenderPayment = 0, nDebtPayment = 0, nPmiPayment = 0;
   var nQualify28 = 0, nQualify36 = 0, nQualifyMinimum = 0;

// if ( (nPayment = Validate(oForm.appn0001.value, 0)) == nErrorNumber)
//    iError = 100;

   if ( (nAnnualTax = Validate(oForm.appn0002.value, 0)) == nErrorNumber)
      iError = 110;

   else if ( (nAnnualInsurance = Validate(oForm.appn0003.value, 0)) == nErrorNumber)
      iError = 120;

   else if ( (nMonthlyDebt = Validate(oForm.appn0004.value, 0)) == nErrorNumber)
      iError = 130;

   else if ( (nSalePrice = Validate(oForm.appn0005.value, 0)) == nErrorNumber)
      iError = 140;

   else if ( (nDownPayment = Validate(oForm.appn0006.value, 0)) == nErrorNumber)
      iError = 150;

// else if ( (nPrincipal = Validate(oForm.appn0007.value, 0)) == nErrorNumber)
//    iError = 160;

   else if ( (nInputInterest = Validate(oForm.appn0008.value, 0)) == nErrorNumber)
      iError = 170;

   else if ( (iYears = Validate(oForm.appn0009.value, 1)) == nErrorNumber)
      iError = 180;

   if (!iError)
   {
      var sMessage = "";
      if (nPayment == 0)
	 sMessage = "Please enter Monthly Mortgage Principal/Interest";
      else if (nPayment < 0)
	 sMessage = "Monthly Mortgage Principal/Interest must be positive";
      else if (nAnnualTax == 0)
	 sMessage = "Please enter Expected Annual Property Tax";
      else if (nAnnualTax < 0)
	 sMessage = "Expected Annual Property Tax must be positive";
      else if (nAnnualInsurance == 0)
	 sMessage = "Please enter Expected Annual Home Insurance Costs";
      else if (nAnnualInsurance < 0)
	 sMessage = "Expected Annual Home Insurance Costs must be positive";
//    else if (nMonthlyDebt == 0)
//	 sMessage = "Please enter Expected Monthly Debt Payments";
      else if (nMonthlyDebt < 0)
	 sMessage = "Expected Monthly Debt Payments must be positive or zero";
      else if (nSalePrice == 0)
	 sMessage = "Please enter Sale Price of Home";
      else if (nSalePrice < 0)
	 sMessage = "Sale Price of Home must be positive";
      else if (nDownPayment == 0)
	 sMessage = "Please enter Down Payment";
      else if (nDownPayment < 0)
	 sMessage = "Down Payment must be positive";
      else if (nDownPayment < .03*nSalePrice)
	 sMessage = "Down Payment must be equal to at least 3% of "
			+ "the sale price of the home";
      else if (nInputInterest == 0)
	 sMessage = "Please enter an interest rate";
      else if (nInputInterest < 0)
	 sMessage = "Interest rate must be positive";
      else if (iYears == 0)
	 sMessage = "Please enter amortized length (in Years)";
      else if (iYears < 0)
	 sMessage = "Amortized length (in Years) must be positive";

      nPrincipal = nSalePrice - nDownPayment;
      if (nPrincipal < 0)
	 nPrincipal = 0;
      var iMonths = 12 * iYears;
      var nPercent = nInputInterest / 1200;

      if (sMessage != "")
      {
	 iError = 170;
	 alert(sMessage);
      }
   }

   if (!iError)
   {
      nPayment = nPrincipal / PresentValue(1, nPercent, iMonths);
      nPayment = Round(nPayment + .005, 2);
      nLenderPayment = Round(nPayment + nAnnualTax/12
      				+ nAnnualInsurance/12, 2);
      nDebtPayment = nLenderPayment + nMonthlyDebt;

//    nPmiPayment = Round((nDownPayment >= .2 * nSalePrice) ? 0
//			: .07 / 12 * (nSalePrice - nDownPayment), 2);
//    nPmiPayment = Round((nDownPayment >= .2 * nSalePrice) ? 0
//			: .07 / 12 * nSalePrice, 2);
      nPmiPayment = Round((nDownPayment >= .2 * nSalePrice) ? 0
			: .007 / 12 * (nSalePrice - nDownPayment), 2);

      nQualify28 = Round((nLenderPayment + nPmiPayment) * (12/.28), 2);

      nQualify36 = Round((nDebtPayment + nPmiPayment) * (12/.36), 2);

      nQualifyMinimum = nQualify28;
      if (nQualifyMinimum < nQualify36)
	 nQualifyMinimum = nQualify36;

      Emit1(shStart, "<span class='tableHeadLeft'>Income Requirement Calculator Results<\/span>");

//    Emit1(shHeadGif, "gifs\income_calc_results.gif");
      Emit1(shHeading2, "<span class='tableHeadLeft'>Income Requirement Calculator Results<\/span>");

      Emit(shBeginTable1);

      EmitRow1("Total Monthly Lender Payment",
      				DollarFormat(nLenderPayment, 0, 2));
      EmitRow1("Total Monthly Debt Payment",
      				DollarFormat(nDebtPayment, 0, 2));
      EmitRow1("Total Monthly PMI Payment",
      				DollarFormat(nPmiPayment, 0, 2));
      EmitRow1("28% Qualifying Annual Income",
      				DollarFormat(nQualify28, 0, 2));
      EmitRow1("36% Qualifying Annual Income",
      				DollarFormat(nQualify36, 0, 2));
      EmitRow1("Minimum Qualifying Annual Income",
      				DollarFormat(nQualifyMinimum, 0, 2));
      Emit(shEndTable);

      Emit(shBeginTable2);
      Emit(shLongText);
      Emit(shEndTable);
      Emit(shEndPage);

   }

   if (!iError)
   {
    if (bDebug && sDump != "")
	 sOut += sNl + "<pre>" + sDump + "</pre>";
//    document.open();
      document.write(sOut);
      document.close();

   }

}

function Dump(sStr) { if (bDebug) sDump += sStr + sNl; }

function Emit(sStr) { sOut += sStr + sNl; }

function Emit1(sStr, s1)
{
   var iK;
   if ( (iK = sStr.indexOf(sSub)) >= 0)
      sStr = sStr.substring(0, iK) + s1
                + sStr.substring(iK + sSub.length);
   Emit(sStr);
}

function Emitx(sStr, sSubs)
{
   var iK, iL, iPos1 = 0, iPos2 = 0;
   while ( (iK = sStr.indexOf(iPos1, sSub)) >= 0)
   {
      if ( (iL = eSubs.indexOf(iPos2, sSep)) < 0)
         iL = eSubs.length();
      sStr = sStr.substring(0, iK)
                        + sSubs.substring(iPos1, iL)
                        + sStr.substring(iK + sSub.length());
      iPos1 = iK + sSub.length();
      if ( (iPos2 = iL + eSep.length()) > sSubs.length())
         iPos2 = sSubs.length();
   }
   Emit(sStr);
}


var sBlanks = "                                             "
                + "                                          ";
var sDashes = "---------------------------------------------"
                + "-----------------------------------------";

var nPowers = [
        0.0000000000000001,
        0.000000000000001,
        0.00000000000001,
        0.0000000000001,
        0.000000000001,
        0.00000000001,
        0.0000000001,
        0.000000001,
        0.00000001,
        0.0000001,
        0.000001,
        0.00001,
        0.0001,
        0.001,
        0.01,
        0.1,
        1.,
        10.,
        100.,
        1000.,
        10000.,
        100000.,
        1000000.,
        10000000.,
        100000000.,
        1000000000.,
        10000000000.];

function Power(n)
{
    return nPowers[n+16];
}

var sMonths = ["January", "February", "March", "April", "May",
        "June", "July", "August", "September", "October",
        "November", "December"];

function Mmm(iK) { if (!(iK >= 1 && iK <= 12)) return "MMM" + iK;
            return sMonths[iK-1].substring(0, 3); }

function ExpN(nX, iN)   // compute x ** n, where n is integral
{
   var nResult = 1;
   var bSign = 0;
   if (iN < 0)
   {
      bSign = 1;
      iN = -iN;
   }
   while (iN > 0)
   {
      if (iN & 1)
         nResult *= nX;
      nX *= nX;
      iN >>= 1;
   }
   if (bSign)
      nResult = 1 / nResult;
   return nResult;
}

function PresentValue(nPayment, nPercent, iNumPeriods)
{
   var nAmount = (Math.abs(nPercent) > 1e-20)
         ? nPayment * (1 - ExpN(1 + nPercent, -iNumPeriods))
                                        / nPercent
         : nPayment * iNumPeriods;
   return nAmount;
}

function SparsePresentValue(nPayment, nPercent, iInterval, iNumPeriods)
{
   var nAmount = (Math.abs(nPercent) > 1e-20)
         ? nPayment * (1 - ExpN(1 + nPercent, -iNumPeriods))
                        / (ExpN(1 + nPercent, iInterval) - 1)
         : nPayment * iNumPeriods;
   return nAmount;
}

function Round(nVal, iD)
{
   var iSign = 1;
   if (nVal < 0)
   {
      nVal = - nVal;
      iSign = -1;
   }
   var iInt = Math.round(nVal);
   if (iD > 0)
      iInt = Math.floor(nVal);
   var nFp = nVal - iInt;
// alert ('iInt, nFp = ' + iInt + ", " + nFp);
   if (iD > 0)
      nFp = Math.round(nFp * Power(iD)) / Power(iD);
   nVal = iSign * (iInt + nFp);
   return nVal;
}

function Round2(nVal, iD, iType)
// iType: -1 = floor, 0 = round, +1 = ceil
{
   var nPow = Power(iD);
   nVal = Math.round(nVal * nPow + iType * .5) / nPow;
// alert(nVal + "/" + iD + "/" + iType + "/" + nPow + "/" + nVal);
   return nVal;
}

function Validate(sVal, bInt)
{
   var sMessage = "";
   var bDot = 0, bE = 0, iState = 0;
   var sCh, iK;
   var bInvalid = 0;
   var nValue = bInt ? parseInt(sVal) : parseFloat(sVal);

   for (iK = 0; sMessage == "" && iK < sVal.length; ++iK)
   {
      sCh = sVal.charAt(iK);
      if (sCh == " ")
      {
         if (iState > 0)
            iState = 9;
      }
      else
      {
         if (iState == 9)
            sMessage = "Number '" + sVal + "' has an embedded blank";
         else if (sCh == '.' && !bInt)
         {
            if (bDot || bE)
	       bInvalid = 1;
            else
               bDot = 1;
         }
         else if ((sCh == 'e' || sCh == 'E') && !bInt)
         {
            if (bE)
	       bInvalid = 1;
            else
            {
               bE = 1;
               iState = 6;
            }
         }
         else if (sCh == '+' || sCh == '-')
         {
            if (iState == 0 || iState == 6)
               ++iState;
            else
               sMessage = "Number '" + sVal + "' contains a sign "
                                + "in an illegal position"
         }
         else if (sCh >= '0' && sCh <= '9')
         {
            if (iState == 1 || iState == 7)
               ++iState;
            else if (iState == 0 || iState == 6)
               iState += 2;
         }
         else
	    bInvalid = 1;
      }
      if (bInvalid)
	 sMessage = "Number '" + sVal + "' contains"
                        + " invalid non-numeric character(s)";
   }

   if (sMessage == "")
      if (iState == 1 || iState == 6 || iState == 7)
         sMessage = "Illegal number: " + sVal;
      else if (iState == 0)
	 nValue = 0;
   if (sMessage != "")
   {
      alert(sMessage);
      nValue = nErrorNumber;
   }
   return nValue
}


// DollarFormat -- could be jazzed up to produce "CR" or "DB"
function DollarFormat(nVal, iW, iD)
{
   return GenFmt(nVal, iW, iD, 1);
}

function Format(nVal, iW, iD)
{
   return GenFmt(nVal, iW, iD, 0);
}

function GenFmt(nVal, iW, iD, bDollar) // format val into w chars,
                        // d digs after decimal point
{
   var sOut = "";
   var iSign = 0;
   nVal = Round(nVal, iD);
   if (nVal < 0)
   {
      nVal = - nVal;
      iSign = 1;
   }
   var iInt = Math.round(nVal);
   if (iD > 0)
      iInt = Math.floor(nVal);
   var nFp = nVal - iInt;
   var iDigs = 1;
   if (iInt > 9)
      iDigs = Math.floor(Math.log(iInt+.1)/Math.log(10)) + 1;
   var iLeft = iW - iSign - (bDollar ? 1 : 0);
   if (iD > 0)
      iLeft -= iD + 1;
   if (iLeft > iDigs)
      sOut += sBlanks.substring(0, iLeft - iDigs);
   if (iSign)
      sOut += '-';
   if (bDollar)
      sOut += '$';
   sOut += iInt;
   if (iD > 0)
   {
      nFp = Math.round((1 + nFp) * Power(iD));
      sOut += '.' + String(nFp).substring(1);
   }
   return sOut;
}

function PrepadString(sStr, iW)
{
   if (sStr.length < iW)
      sStr = sBlanks.substring(0, iW - sStr.length) + sStr;
   return sStr;
}

function CenterString(sStr, iW)
{
   var iBlanks = iW - sStr.length;
   if (iBlanks > 0)
      sStr = sBlanks.substring(0, Math.floor(iBlanks/2)) + sStr
                + sBlanks.substring(0, iBlanks - Math.floor(iBlanks/2));
   return sStr;
}
