/************************************************************************/
/* TaxSolve_NJ_1040_2005.c - 						*/
/* Copyright (C) 2005 - Aston Roberts					*/
/* 									*/
/* Compile:   gcc taxsolve_NJ_1040_2005.c -o taxsolve_NJ_1040_2005	*/
/* Run:	      ./taxsolve_NJ_1040_2005  NJ_1040_2005.dat 		*/
/* 									*/
/* GNU Public License - GPL:						*/
/* This program is free software; you can redistribute it and/or	*/
/* modify it under the terms of the GNU General Public License as	*/
/* published by the Free Software Foundation; either version 2 of the	*/
/* License, or (at your option) any later version.			*/
/* 									*/
/* This program is distributed in the hope that it will be useful,	*/
/* but WITHOUT ANY WARRANTY; without even the implied warranty of	*/
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU	*/
/* General Public License for more details.				*/
/* 									*/
/* You should have received a copy of the GNU General Public License	*/
/* along with this program; if not, write to the Free Software		*/
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA		*/
/* 02111-1307 USA							*/
/* 									*/
/* Aston Roberts 1-2-2004	aston_roberts@yahoo.com			*/
/* Updates by:  Aston Roberts 1-18-2005					*/
/*    2-14-05   BWB							*/
/************************************************************************/

#include <stdio.h>
#include <time.h>

#include "taxsolve_routines.c"

float thisversion=3.1;
float A[MAX_LINES], S[MAX_LINES], E[MAX_LINES];

#define SINGLE 		        1
#define MARRIED_FILLING_JOINTLY 2
#define MARRIED_FILLING_SEPARAT 3
#define HEAD_OF_HOUSEHOLD       4
#define WIDOW		        5

float TaxRateFunction( float x, int status )
{

 if ((status==SINGLE) || (status==MARRIED_FILLING_SEPARAT))	/* Single, Married/sep */
  {
   if (x<20000.0) return x * 0.014; else
   if (x<35000.0) return x * 0.0175 - 70.0; else
   if (x<40000.0) return x * 0.035 - 682.5; else
   if (x<75000.0) return x * 0.05525 - 1492.5; else
   if (x<500000.0) return x * 0.0637 - 2126.25;
   return x * 0.0897 - 15126.25;
  }
 else
 if ((status==MARRIED_FILLING_JOINTLY) || (status==HEAD_OF_HOUSEHOLD) || (status==WIDOW))	 /* Married/Joint, HouseHead, widower. */
  {
   if (x<20000.0) return x * 0.014; else
   if (x<50000.0) return x * 0.0175 - 70.0; else
   if (x<70000.0) return x * 0.0245 - 420.0; else
   if (x<80000.0) return x * 0.035 - 1154.5; else
   if (x<150000.0) return x * 0.05525 - 2775.0; else
   if (x<500000.0) return x * 0.0637 - 4042.5;
   return x * 0.0897 - 17042.5;
  }
 else {printf("Status not covered.\n"); exit(0);}
}




/*----------------------------------------------------------------------------*/

int main( int argc, char *argv[] )
{
 int i, j, k;
 char word[1000], outfname[1000];
 int status=0;
 time_t now;
 int L12a=0, L12b=0;
 float L19b=0.0, L29a=0.0, L29b=0.0;
 float Ab[10];

 /* Intercept any command-line arguments. */
 printf("NJ 1040 2005 - v%3.1f\n", thisversion);
 i = 1;  k=1;
 while (i < argc)
 {
  if (strcmp(argv[i],"-verbose")==0)  verbose = 1;
  else
  if (k==1)
   {
    infile = fopen(argv[i],"r");
    if (infile==0) {printf("ERROR: Parameter file '%s' could not be opened.\n", argv[i]); exit(1);}
    k = 2;
    /* Base name of output file on input file. */
    strcpy(outfname,argv[i]);
    j = strlen(outfname)-1;
    while ((j>=0) && (outfname[j]!='.')) j--;
    if (j<0) strcat(outfname,".out"); else strcpy(&(outfname[j]),".out");
    outfile = fopen(outfname,"w");
    if (outfile==0) {printf("ERROR: Output file '%s' could not be opened.\n", outfname); exit(1);}
    printf("Writing results to file:  %s\n", outfname);
   }
  else {printf("Unknown command-line parameter '%s'\n", argv[i]); exit(1);}
  i = i + 1;
 }

 if (infile==0) {printf("Error: No input file on command line.\n"); exit(1);}

 /* Pre-initialize all lines to zeros. */
 for (i=0; i<MAX_LINES; i++) 
  {
   L[i] = 0.0;
   A[i] = 0.0;
   S[i] = 0.0;
   E[i] = 0.0;
  }

 /* Accept parameters from input file. */
 /* Expect  NJ-1040 lines, something like:
	Title:  NJ 1040 1999 Return
	L14		{Wages}
	L15a		{Interest}
	L16		{Dividends}
	L18		{Capital Gains}
	S1		{Property Tax}
	L42		{Witheld tax, from W-2}
*/


 /* Accept Form's "Title" line, and put out with date-stamp for records. */
 read_line( infile, word );
 now = time(0);
 fprintf(outfile,"\n%s		%s\n", word, ctime( &now ));

 /* get_parameter(infile, kind, x, emssg ) */
 get_parameter( infile, 's', word, "Status" );
 get_parameter( infile, 'l', word, "Status ?");
 if (strncasecmp(word,"Single",4)==0) status = SINGLE; else
 if (strncasecmp(word,"Married/Joint",13)==0) status = MARRIED_FILLING_JOINTLY; else
 if (strncasecmp(word,"Married/Sep",11)==0) status = MARRIED_FILLING_SEPARAT; else
 if (strncasecmp(word,"Head_of_House",4)==0) status = HEAD_OF_HOUSEHOLD; else
 if (strncasecmp(word,"Widow",4)==0) status = WIDOW;
 else
  { 
   printf("Error: unrecognized status '%s'. Must be: Single, Married/joint, Married/sep, Head_of_house, Widow(er)\nExiting.\n", word); 
   exit(0); 
  }
 switch (status)
 {
  case SINGLE: 			fprintf(outfile,"Status = Single (%d)\n", status); break;
  case MARRIED_FILLING_JOINTLY: fprintf(outfile,"Status = Married/Joint (%d)\n", status); break;
  case MARRIED_FILLING_SEPARAT: fprintf(outfile,"Status = Married/Sep (%d)\n", status); break;
  case HEAD_OF_HOUSEHOLD: 	fprintf(outfile,"Status = Head_of_Household (%d)\n", status); break;
  case WIDOW: 		  	fprintf(outfile,"Status = Widow(er) (%d)\n", status); break;
 }

 get_parameter( infile, 's', word, "L6" );	/* Exemptions, self/spouse. */
 get_parameter( infile, 'i', &j, "L6"); 
 L[6] = j;
 shownum(6); 

 get_parameter( infile, 's', word, "L7" );	/* Exemptions, Over 65. */
 get_parameter( infile, 'i', &j, "L7"); 
 L[7] = j;
 shownum(7); 

 get_parameter( infile, 's', word, "L8" );	/* Exemptions, Blind/disabled. */
 get_parameter( infile, 'i', &j, "L8"); 
 L[8] = j;
 shownum(8); 

 get_parameter( infile, 's', word, "L9" );	/* Exemptions, children. */
 get_parameter( infile, 'i', &j, "L9"); 
 L[9] = j;
 shownum(9); 

 get_parameter( infile, 's', word, "L10" );	/* Exemptions, other dependents. */
 get_parameter( infile, 'i', &j, "L10"); 
 L[10] = j;
 shownum(10); 

 get_parameter( infile, 's', word, "L11" );	/* Exemptions, college kids. */
 get_parameter( infile, 'i', &j, "L11"); 
 L[11] = j;
 shownum(11); 

 L12a = L[6] + L[7] + L[8] + L[11];
 fprintf(outfile,"L12a = %d\n", L12a);
 L12b = L[9] + L[10];
 fprintf(outfile,"L12b = %d\n", L12b);

 GetLineF( "L14", &L[14] );	/* Wages. */

 GetLineF( "L15a", &L[15] );	/* Taxable Interest. */

 GetLineF( "L16", &L[16] );	/* Dividends. */

 GetLineF( "L17", &L[17] );	/* Business profits, Fed Sched C. */

 GetLine( "L18", &L[18] );	/* Capital Gains . */
 if (L[18]<0.0) L[18] = 0.0;
 showline(18);

 GetLineF( "L19a", &L[19] );	/* Pensions, taxable amount received. */

 GetLineF( "L19b", &L19b );	/* NJ pension exclusion. */
 L[19] = L[19] - L19b;
 showline(19);

 GetLineF( "L20", &L[20] );	/* Partnership income. (See pg 30.) */

 GetLineF( "L21", &L[21] );	/* S Corporation income. (See pg 30.) */

 GetLineF( "L22", &L[22] );	/* Rent, royalty, patents income. (Sched C line 3.) */

 GetLineF( "L23", &L[23] );	/* Net gambling winnings. */

 GetLineF( "L24", &L[24] );	/* Alimony and maintenance payments RECEIVED. */

 GetLineF( "L25", &L[25] );	/* Other (See pg 31). */

 L[26] = L[14] + L[15] + L[16] + L[17] + L[18] + L[19] + L[20] + L[21] + L[22] + L[23] + L[24] + L[25];
 showline_wmsg(26,"Total Income");	/* Total Income. */

 GetLineF( "L27", &L[27] );	/* Other Retirement Income (See worksheet pg 37). */

 L[28] = L[26] - L[27];
 showline_wmsg(28,"NJ Gross Income");

 L29a = L12a * 1000.0;
 fprintf(outfile," L29a = %6.2f\n", L29a );
 L29b = L12b * 1500.0;
 fprintf(outfile," L29b = %6.2f\n", L29b );
 L[29] = L29a + L29b;
 fprintf(outfile,"L29c = %6.2f	Total Exemption Amount\n", L[29] );

 fprintf(outfile,"\n");
 GetLine( "E1", &E[1] );	/* Medical Expenses (See pg 35). */
 showline_wrksht('E',1,E);
 E[2] = 0.02 * L[28];
 showline_wrksht('E',2,E);
 E[3] = NotLessThanZero( E[1] - E[2] );
 showline_wrksht('E',3,E);
 GetLine( "E4", &E[4] );      /* Qualified Archer MSA contributions from Federal Form 8853 */
 showline_wrksht('E',4,E);
 GetLine( "E5", &E[5] );      /* Amount of self-employed health insurance deduction */
 showline_wrksht('E',5,E);
 E[6] = NotLessThanZero( E[3] + E[4] + E[5] );
 showline_wrksht('E',6,E);
 fprintf(outfile,"\n");
 L[30] = E[6];
 showline_wmsg(30," Medical Expenses Worksheet E (See pg 38)");
 /* end of Worksheet E */

 GetLineF( "L31", &L[31] );	/* Alimony and maintenance payments PAYED. */

 GetLineF( "L32", &L[32] );	/* Qualified Conservation Contribution. */

 GetLineF( "L33", &L[33] );	/* Health Enterprise Zone Deduction. */

 L[34] = L[29] + L[30] + L[31] + L[32] + L[33];
 showline_wmsg(34,"Total Exemptions and Deductions");

 /* Taxable income. */
 L[35] = L[28] - L[34];
 if (L[35]>0.0)
  showline_wmsg(35,"(Taxable Income)");

 fprintf(outfile,"\n");  /* Tax deduction worksheet. */
 GetLine( "S1", &S[1] );
 showline_wrksht('S',1,S);

 S[2] = smallerof( S[1], 10000.0 );
 showline_wrksht('S', 2, S);

 S[3] = L[35];
 showline_wrksht('S',3,S);
 S[4] = S[2];
 showline_wrksht('S',4,S);
 S[5] = S[3] - S[4];
 showline_wrksht('S',5,S);
 S[6] = TaxRateFunction( S[5], status );
	fprintf(outfile,"		6a. Tax Amount with PropTax Deduction=%6.2f\n", S[6]);
	fprintf(outfile,"		6b. Tax Amount without PTax Deduction=%6.2f\n", TaxRateFunction( S[3], status ));
 showline_wrksht('S',6,S);
 S[7] = TaxRateFunction( S[3], status ) - S[6];
 showline_wrksht('S',7,S);
 if (S[7] >= 50.0) 
  {
   fprintf(outfile," Yes: Take PropTax Deduction\n\n");
   L[36] = S[4];
   showline(36);
   L[46] = 0.0;
   showline(46);
  }
 else
  {
   fprintf(outfile," No: Take PropTax Credit\n\n");
   L[36] = 0.0;
   showline(36);
   L[46] = 50.0;
   showline(46);
  }
 
 fprintf(outfile,"\n");  /* NJ Taxable Income.*/
 L[37] = L[35] - L[36];
 if (L[37]>0.0)
  showline_wmsg(37,"NJ Taxable Income");

 L[38] = TaxRateFunction( L[37], status );
 showline_wmsg(38,"TAX");

 GetLine( "A1", &A[1] );
 GetLine( "A9a", &A[9] );
 if (A[1]>0.0)
  {
   fprintf(outfile,"\nSchedule A:\n");
   showline_wrksht('A',1,A); 
   A[2] = L[28];
   showline_wrksht('A',2,A); 
   A[3] = A[1] / A[2];
   fprintf(outfile," A3 = %6.2f %%\n", 100.0 * A[3]);
   A[4] = L[35];
   fprintf(outfile," A4a = %6.2f	A4b = %6.2f\n", A[4], A[4]);
   A[5] = L[36];
   fprintf(outfile," 5a = %6.2f\n", A[5] );
   A[5] = smallerof( A[5], 10000.0 );
   fprintf(outfile," A5a = %6.2f	A5b = %6.2f\n", A[5], 0.0);
   A[6] = A[4] - A[5];
   Ab[6] = A[4] - 0.0;
   fprintf(outfile," A6a = %6.2f	A6b = %6.2f\n", A[6], Ab[6]);
   A[7] = TaxRateFunction( A[6], status );
   Ab[7] = TaxRateFunction( Ab[6], status );
   fprintf(outfile," A7a = %6.2f	A7b = %6.2f\n", A[7], Ab[7] );
   A[8] = A[3] * A[7];
   Ab[8] = A[3] * Ab[7];
   fprintf(outfile," A8a = %6.2f	A8b = %6.2f\n", A[8], Ab[8] );
   fprintf(outfile,"  9a = %6.2f\n", A[9]);
   Ab[9] = smallerof( A[9], Ab[8] );
   A[9] = smallerof( A[9], A[8] );
   fprintf(outfile," A9a = %6.2f	A9b = %6.2f\n", A[9], Ab[9] );
   if (A[9] > L[38])  
    L[39] = L[38];  
   else  
    L[39] = A[9];
   showline_wmsg(39,"( Credit for Taxes paid to other jurisdictions. )\n");
  }

 L[40] = L[38] - L[39];
 showline_wmsg(40,"( Balance of Tax )");
 L[41] = L[40];
 showline_wmsg(41,"( Total Tax )");

 GetLineF( "L42", &L[42] );	/* Use Tax Due on Out-of-State Purchases (pg 44). */
 GetLineF( "L43", &L[43] );	/* Penalty for underpayment of estimated tax. */

 L[44] = L[41] + L[42] + L[43];
 showline(44);			/* Total Tax + Penalty. */

 GetLine( "L45", &L[45] );
 showline_wmsg(45,"Total NJ Income Tax Withheld");

 showline_wmsg(46,"Property tax Credit");

 GetLineF( "L47", &L[47] );	/* NJ Estimated Tax Payments/Credit from 2004 return. */

 GetLineF( "L48", &L[48] );	/* NJ Earned Income Tax Credit. (See Sched pg 3.) */

 GetLineF( "L49", &L[49] );	/* EXCESS NJ UI/HC/WD Withheld, (See pg 47.) */

 GetLineF( "L50", &L[50] );	/* EXCESS NJ Disability Insurance Withheld, (See pg 47.) */

 L[51] = L[45] + L[46] + L[47] + L[48] + L[49] + L[50];
 showline_wmsg(51,"Total Payments/Credits");
 
 if (L[51] < L[44])
  {
   L[52] = L[44] - L[51];
   fprintf(outfile,"L52 = %6.2f	YOU OWE !!!\n", L[52] );
  }
 else
  {
   L[53] = L[51] - L[44];
   fprintf(outfile,"L53 = %6.2f	REFUND !!!\n", L[53] );

   L[61] = 0.0;
   showline_wmsg(61,"( Total Contributions from overpayment )");
   L[62] = L[53] - L[61];
   showline(62);
  }
 
 fclose(infile);
 fclose(outfile);
 Display_File( outfname );
 printf("\nResults written to file:  %s\n", outfname);
 return 0;
}
