/************************************************************************/
/* TaxSolve_NC_D400_2005.c - North Carolina 2005 NC-DC400 State Taxes.	*/
/* Copyright (C) 2004, 2005 - S.Jenkins					*/
/* 									*/
/* Compile:   gcc taxsolve_NC_D400_2005.c -o taxsolve_NC_D400_2005	*/
/* Run:  ./taxsolve_NC_D400_2005		  			*/
/*  Uses log from TaxSolve Federal 1040.				*/
/* 									*/
/* 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							*/
/* 									*/
/* 1-30-2004	http://opentaxsolver.sourceforge.com/			*/
/* 2-8-2005     Updated for 2004 tax year.				*/
/* 3-15-2006    Updated for 2005 tax year.				*/
/************************************************************************/

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>

#include "taxsolve_routines.c"

float thisversion=3.0;
#define SINGLE                  1
#define MARRIED_FILLING_JOINTLY 2
#define MARRIED_FILLING_SEPARAT 3
#define HEAD_OF_HOUSEHOLD       4
#define WIDOW                   5
#define Yes 1
#define No  0

float TaxRateFunction( float x, int status )
{
 switch (status)
  {
   case 1:	/*Single*/
	if (x<12750.0) return 0.06 * x; else
	if (x<60000.0) return 765.0 + 0.07 * (x-12750.0); else
	if (x<120000.0) return 4072.5 + 0.0775 * (x-60000.0); else
	return 8722.5 + 0.0825 * (x-120000.0);
	break;
   case 2:	/*Married/joint*/
   case 5:	/*Widow(er)*/
	if (x<21250.0) return 0.06 * x; else
	if (x<100000.0) return 1275.0 + 0.07 * (x-21250.0); else
	if (x<200000.0) return 6787.5 + 0.0775 * (x-100000.0); else
	return 14537.5 + 0.0825 * (x-200000.0);
	break;
   case 3:	/*Married/Separate*/
	if (x<10625.0) return 0.06 * x; else
	if (x<50000.0) return 765.0 + 0.07 * (x-10625.0); else
	if (x<100000.0) return 4072.5 + 0.0775 * (x-50000.0); else
	return 8722.5 + 0.0825 * (x-100000.0); 
	break;
   case 4:	/*Head of Household*/
	if (x<17000.0) return 0.06 * x; else
	if (x<80000.0) return 1020.0 + 0.07 * (x-17000.0); else
	if (x<160000.0) return 5430.0 + 0.0775 * (x-80000.0); else
	return 11630.0 + 0.0825 * (x-160000.0);
	break;
  }
 return 0.0; 
}


struct FedReturnData
 {
  float fedline[100];
  int Exception, Itemized;
 };


void ImportFederalReturnData( char *fedlogfile, struct FedReturnData *fed_data )
{
 FILE *infile;
 char fline[1000], tmpstr[1000], word[1000];
 int linenum;

 infile = fopen(fedlogfile, "r");
 if (infile==0) {printf("Error: Could not open federal return '%s'\n", fedlogfile); exit(0);}
 fed_data->Itemized = 1; /* Set initial default values. */
 for (linenum=0; linenum<100; linenum++) fed_data->fedline[linenum] = 0.0;
 read_line(infile,fline);  linenum = 0;
 while (!feof(infile))
  {
   if (strstr(fline,"Use standard deduction.")!=0) fed_data->Itemized = 0;
   next_word(fline, tmpstr, word, " 	=");
   if ((strstr(word,"L")==word) && (strstr(fline," = ")!=0))
    {
     if (sscanf(&word[1],"%d",&linenum)!=1) printf("Error: Reading fed line number '%s%s'\n",word,fline);
     next_word(fline, tmpstr, word, " 	=");
     if (sscanf(word,"%f", &fed_data->fedline[linenum])!=1) 
	printf("Error: Reading fed line %d '%s%s'\n",linenum,word,fline);
     if (verbose) printf("FedLin[%d] = %2.2f\n", linenum, fed_data->fedline[linenum]);
    }
   read_line(infile,fline);
  }
 fclose(infile);
}



int main( int argc, char *argv[] )
{
 int i, j, k, status, Exception;
 char word[1000], outfname[1000];
 time_t now;
 struct FedReturnData fed_data;
 float AB=0.0;


 /*-----------------------------------------*/
 /* --- Decode any command line options. -- */
 /*-----------------------------------------*/
 printf("NC D400 2005 - v%3.2f\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);}
 

 /*--------------------------*/
 /* ---- Get Input Data ---- */
 /*--------------------------*/

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

 /* Accept parameters from input file. */
 /* Expect  D-400 lines, something like:
	Title:  NC-400 1999 Return
	L12	34900.0  {Wages}
 */

 /* Accept Form's "Title" line, and put out with date-stamp for your 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, "FedReturn" );	/* File name of Federal Return log file. */
 get_word( infile, word );
 ImportFederalReturnData( word, &fed_data);

 get_parameter( infile, 's', word, "Status"); /* 1=single, 2=married/joint, 3=married/separate, 4=house-head, 5=widow */
 get_parameter( infile, 'l', word, "Status ?");
 if ((word[0]>'0') && (word[0]<'6')) status = word[0]-48; else
 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); 
  }
 fprintf(outfile,"Status = %s (%d)\n", word, status);

 /* Answer yes, if 65 or over, or blind, or you are claimed as someone else's dependent, or */
 /* married filing separate and spouse claims deductions, else answer no. */
 get_parameter( infile, 's', word, "Exception" );
 get_parameter( infile, 'b', &Exception, "Exception?"); 
 if (Exception==1) { printf("Exception case not handled.\n"); exit(0);} 

 GetLine( "L12", &L[12] );     /* Part-year residents, amnt from line 52, else 1.0. */

 GetLine( "L15", &L[15] );	/* Tax credits. (D-400TC part 4 line 32)*/

 GetLine( "L17", &L[17] );	/* Consumer Use Tax. (pg 6)*/

 GetLine( "L19", &L[19] );	/* North Carolina Income Tax Withheld */

 GetLine( "L20", &L[20] );     /* Other tax payments. */

		/* If you itemized, enter following, else enter 0. */
 GetLine( "L32", &L[32] );     /* State and local income taxes on Sched A line 5 */
 				/* Also list any foreign income taxes (Sched A line 8) */

 GetLine( "L35", &L[35] );	/* Interest income frm non-NC states. */

 GetLine( "L36", &L[36] );	/* Additional 1st yr deprec. adjustment */

 GetLine( "L37", &L[37] );	/* Other additions to fed income */

 GetLine( "L40", &L[40] );	/* Interest from US or NC obligations. */

 GetLine( "L41", &L[41] );	/* Taxable soc sec and RR benfits. */

 GetLine( "L42", &L[42] );	/* Retirement benefits (Bailey)*/

 GetLine( "L43", &L[43] );	/* Other retirement benefits */

 GetLine( "L44", &L[44] );	/* Severance wages (See Line instructions on Page 13) */

 GetLine( "L45", &L[45] );	/* Adjust additional 1st yr deprec. 2002, 2003, and 2004 */

 GetLine( "L46", &L[46] );	/* Other deductions from fed income */

 fclose(infile);


 /*-------------------------------*/
 /* ---- Do Tax Calculations ---- */
 /*-------------------------------*/

 L[6] = fed_data.fedline[43];		/* Taxable income from Fed1040 Line 43. */
 L[29] = fed_data.fedline[40];		/* Itemized deductions or std. deduction from Fed1040 line 40. */
 
 switch (status)
  {
   case 1: L[30] = 3000.0; break;  /* NC std single deduction. */
   case 2: L[30] = 6000.0; break;  /* NC std Married/joint deduction. */
   case 3: L[30] = 3000.0; break;  /* NC std Married/sep deduction. */
   case 4: L[30] = 4400.0; break;  /* NC std Head of house deduction. */
   case 5: L[30] = 6000.0; break;  /* NC std widow(er) deduction. */
  }

 L[31] = L[29] - L[30];
 if (L[31]<0.0) L[31] = 0.0;

 if (L[32]==0.0)     L[33] = L[31];
 else
 if (L[31] < L[32])  L[33] = L[31];  
 else                L[33] = L[32];

 switch (status)
  {
   case 1: AB =  60000.0; break;  /* NC std single */
   case 2: AB = 100000.0; break;  /* NC std Married/joint */
   case 3: AB =  50000.0; break;  /* NC std Married/sep */
   case 4: AB =  80000.0; break;  /* NC std Head of house */
   case 5: AB = 100000.0; break;  /* NC std widow(er) */
  }

 if (fed_data.fedline[36] < AB)		/* Compare Fed AGI */
  { /*A*/
    L[34] = fed_data.fedline[6] * 600.0;	/* Check instructions pg 9 */
  } /*A*/
 else
  { /*B*/
    L[34] = fed_data.fedline[6] * 1100.0;	/* Check instructions pg 9 */
  } /*B*/

 L[38] = L[33] + L[34] + L[35] + L[36] + L[37];	 /* Total additions. */

 L[7] = L[38];			/* Additions to Federal Taxable Income. */

 L[8] = L[6] + L[7];

 L[39] = fed_data.fedline[10];

 L[47] = L[39] + L[40] + L[41] + L[42] + L[43] + L[44] + L[45] + L[46];

 L[9] = L[45];			/* Deductions from federal taxable income. */	

 L[10] = L[8] - L[9];

 L[11] = L[10];

 L[13] = L[12] * L[11];

 if (L[13] <= 68000.0)
  {
   int m;
   float x;

   m = L[13] / 50.0;    /* Round income to nearest $50. */
   x = TaxRateFunction( 50.0 * (float)m + 25.0, status );       /* Lookup. */
   m = (int)(x + 0.5);  /* Round result to whole dollar. */
   L[14] = (float)m;
  }
 else L[14] = TaxRateFunction( L[13], status );

 L[16] = L[14] - L[15];

 L[18] = L[16] + L[17];

 L[21] = L[19] + L[20];

 if (L[18] > L[21]) 
  {
   L[22] = L[18] - L[21];	/* You OWE */
   L[23] = L[22];  /* Assumes no penalties. */
  }
 else
  {
   L[24] = L[21] - L[18];	
   L[25] = 0.0;  /* Apply estimated 2005 tax. */
   L[26] = 0.0;  /* Wildlife fund. */
   L[27] = L[25] + L[26];
   L[28] = L[24] - L[27];	/* REFUND */
  }



 /*-------------------------*/
 /* ---- Print Results ---- */
 /*-------------------------*/

 showline(6);	/* Taxable fed income */
 showline(7);	/* Additions to fed income */
 showline(8);	
 showline(9);	/* Deductions */
 showline(10);
 showline(11);
 if (L[12]<1.0) showline(12);	/* Part-yr */
 showline_wmsg(13,"North Carolina Taxable Income");
 showline_wmsg(14,"North Carolina Income Tax");
 showline(15);
 showline(16);
 showline(17);
 showline(18);
 showline_wmsg(19,"North Carolina Tax Withheld");
 showline_wmsg(20,"Other Tax Payments");
 showline(21);
 if (L[18] > L[21])
  {
   showline(22);
   showline_wmsg(23,"PAY THIS AMOUNT");
  }
 else
  {
   showline(24);
   showline(25);
   showline(26);
   showline(27);
   showline_wmsg(28,"AMOUNT TO BE REFUNDED");
  }

 for (k=29; k<=47; k++)
  showline(k);

 fclose(outfile);
 printf("\nResults written to file '%s'\n", outfname);
 // Display_File( outfname );
 return 0;
}
