// mortgage.c amount duration rate
// prints a schedule of monthly payments, broken down
// by principal and interest, then prints totals for
// the principal, interest, and total amount paid
// compile as cc -g -Xcpluscomm -o mortgage mortgage.c -lm

#include <stdio.h>
#include <math.h>

// extra payments
double *extras;

int
main (
    int	argc,
    char *argv[])
{
double A, uR, R;
int Y;
double M;
int N;
double P, T, I, B;
int m;
double totalT, totalI, totalP;
int totalM = 0;
int gap = 36;

    if ( argc < 4 || argc > 5 ) {
	fprintf (stderr, "usage: %s amount(dollars) duration(years) rate(percent per year) [n]\n", argv[0]);
	fprintf (stderr, "prints first and last n payments of specified loan amount and period\n");
	exit (-1);
	}

    A = atof (argv[1]);	    // loan amount
    Y = atoi (argv[2]);	    // number of years
    uR = atof (argv[3]);    // interest rate, in percent
    if ( argc == 5 ) 	    // number of months to print
	gap = atoi (argv[4]);
    R = uR / 100.;	    // convert to decimal

    M = R / 12.0;	    // monthly interest rate
    N = Y * 12;		    // number of monthly payments

    // get space for extra payments, if any
    extras = (double *) calloc ( N+1, sizeof (double) );
    extras[0] = -1;	// one-relative array

    // test -- 10K payment in 24th month
    extras[24] = 10000.;

    // initialize the balance to B_0 = loan amount
    B = A;

    // compute the first principal payment P_1
    // from closed-form expression derived elsewhere
    P = (M * A) / (pow(M + 1., N) - 1.);

    // compute the total monthly payment T
    // from closed-form expression derived elsewhere
    T = pow(M + 1., (double)N) * P;

    // print intro
    printf ( "\nMonthly payments on a %d-year loan of %d dollars at %5.3lf%% per year:\n\n",
			Y, (int)A, uR );

    // print headers
    printf ( "%6s\t%9s\t%9s\t%9s\t%9s\t%7s\n",
	    "Pymt #", "Amount", "Principal", "Interest", "Balance", " % Paid");
    printf ( "%6s\t%9s\t%9s\t%9s\t%9s\t%7s\n",
	    "------", "------", "---------", "--------", "-------", " ------");
    printf ( "%6s\t%9s\t%9s\t%9s\t%9.2lf\n",
	    "", "", "", "", B );

    // print amortization schedule
    totalT = totalI = totalP = 0;
    for ( m = 1; m <= N; m++ ) {

        // compute this month's interest on balance
        I = M * B;

	// compute the principal payment as T - I
	P = T - I;

	// subtract the principal from the balance
	B -= P;

	if ( m <= gap || m > N-gap ) {
	    // print payment number, payment, principal, interest, balance, % paid
	    printf ( "%6d\t%9.2lf\t%9.2lf\t%9.2lf\t%9.2lf\t%7.2f\n",
		    m, T, P, I, B, (100. - (100. * B)/A) );
	    }

	// apply extra payment, if any
	if ( extras[m] > 0.0 ) {
	    B -= extras[m];
	    totalP += extras[m];
	    totalT += extras[m];
	    // print payment number, payment, principal, interest, balance, % paid
	    printf ( "**%4d\t%9s\t%9.2lf\t%9s\t%9.2lf\t%7.2f\n",
		    m, " ", extras[m], " ", B, (100. - (100. * B)/A) );
	    }
	
	if ( m == gap+1 && gap < N-gap )
	    printf ( "...\n");

	// update totals
	totalT += T;
	totalI += I;
	totalP += P;
	totalM += 1;

	// if we have paid off loan, exit
	if ( B <= 0. )
	    break;
	}

    // print loan totals
    printf ( "\nTotals\n");
    printf ( "%6s\t%9s\t%9s\t%9s\n",
	    "Pymts", "Amount", "Principal", "Interest");

    printf ( "%6d\t%9.2lf\t%9.2lf\t%9.2lf\n",
		    totalM, totalT, totalP, totalI );
}
