/*
================================ COPYRIGHT ================================
The contents of this file are subject to the VTech Informations Ltd. License
of VT-OS Ver. 1.1 operating system (the "License"); you may not use this 
file except in compliance with the License.  

Software distributed under the License is distributed on an "AS IS" basis, 
WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License 
for the specific language governing rights and limitations under the License.
  
The Original Code is VT-OS Ver. 1.1 Operating System, released 
on October 1st, 1999
	
The Initial Developer of the Original Code is VTech Informations Ltd.  All 
codes are Copyright (C) VTech Informations Ltd. 1999.  All Rights Reserved.
===========================================================================
*/

/*
===========================================================================
File        :   loan.c
Author(s)   :   Henry Fok, Jason Ngan
Company     :   VTech Informations Ltd.
Project     :   Helio 
Date:	    :   October 1st, 1999
Purpose:	:   application c file
Revision    :   1.1
Note        :   None
===========================================================================
*/              


#include "stdafx.h"

#include "app.h"
#include "appfunc.h"

//#define     DEBUG
//#define DEBUG_LOAN

#define		DELTA			0.00000000001
#define		NUM_ITERATION	1000
#define		INFINITY_RATE	100000

double  dabs(double input)
{
    return (input<0 ? -input : input);
}

double	f(double xi, double n, double m, double p)
{
	return (m/p - m/p*pow(1+xi, -n) - xi);
}


double	fprime(double xi, double n, double m, double p)
{
	return (m*n/p*pow(1+xi, -n-1)-1);
}


double	Newton(double y, double m, double p)
{
	UWORD	i;
    double  x0, xi, n, fpi;
	
	
	n = 12.0*y;
	x0 = y * m / p;
	xi = x0;
	
	for(i = 0; i<NUM_ITERATION; i++)
	{
		x0 = xi;
		fpi = fprime(x0, n, m, p);
		if (fpi == 0.0)
			return -1.0;
		xi = x0 - f(x0, n, m, p) / fpi;
#ifdef PR31700
		if (isinf(xi))
			return -1.0;
#endif
#ifdef PC_SIM
		if (xi > INFINITY_RATE)
			return -1.0;
#endif
        if (dabs(xi - x0) < DELTA)
			return xi*12.0*100;
	}
	return -1.0;
}



/********************************************************
* Function:	LoanCalculation
* Purpose: 	This fucntion is called to calculate the requried 
value				
* Scope:		Application
* Input:		None
* Output:		None
* Return:		None
* Comment: 	None
*********************************************************/
BOOLEAN LoanCalculation(void)
{
	BYTE        num_empty_item = 0, *temp_text, *textbox_text, *source_text, *output_string;
	ObjectID    i, j;
    BYTE        k;
    double      total_payment, total_interest, result, item_value[4], temp, temp1;
    BOOLEAN     error = FALSE;
    BYTE        string[200];
    BYTE        object_type;
    Control     *control_ptr;
    BOOLEAN     found_decimal = FALSE;
    BYTE        debug[200];
	
	if (calculating_item == NO_SELECTION)
	{
		for (i = TEXTBOX_LOAN_NUM_YEARS; i <= TEXTBOX_LOAN_MONTHLY_PAYMENT; i++)
		{
			TextboxGetTextPointer(i, &textbox_text);
			if (strlen(textbox_text) == 0)
			{
				num_empty_item ++;
				if (num_empty_item > 1)
				{
					calculating_item = NO_SELECTION;
					return FALSE;
				}
				else calculating_item = (BYTE)(i - TEXTBOX_LOAN_NUM_YEARS);
			}
		}
	}
	
	
    if (calculating_item != NO_SELECTION)
    {
        FormSetControlGroupSelection(FORM_LOAN, (ObjectID)(calculating_item + CHECKBOX_LOAN_NUM_YEARS));
        for (i = CHECKBOX_LOAN_NUM_YEARS; i <= CHECKBOX_LOAN_MONTHLY_PAYMENT; i ++)
        {
            FormGetObjectPointer((ObjectID)(i), &object_type, (void**)&control_ptr);
            if (i == (calculating_item + CHECKBOX_LOAN_NUM_YEARS))
                control_ptr->control_attr.control_enable = FALSE;
            else control_ptr->control_attr.control_enable = TRUE;
        }
    }
	
	
    if (num_empty_item > 1)
		return FALSE;
	
	
	for (i = TEXTBOX_LOAN_NUM_YEARS; i <= TEXTBOX_LOAN_MONTHLY_PAYMENT; i++)
	{
		if (calculating_item == (BYTE)(i - TEXTBOX_LOAN_NUM_YEARS))
			continue;			
		TextboxGetTextPointer(i, &textbox_text);
		item_value[(i - TEXTBOX_LOAN_NUM_YEARS)] = atod((char*)textbox_text);
		
	}
	
#ifdef DEBUG_LOAN
    dtoa(item_value[0], debug, 20);
    printf("\n item_value[0] = %s", debug);
    dtoa(item_value[1], debug, 20);
    printf("\n item_value[1] = %s", debug);
    dtoa(item_value[2], debug, 20);
    printf("\n item_value[2] = %s", debug);
#endif    
	
	
	
	// CALCULATION here !!!
#ifdef PC_SIM
    total_payment = (double)99999999999.0;
    total_interest = (double)99999999999.0;
    result = (double)999999999.0;
#endif
	
	
    if (item_value[0] == 0 && calculating_item != 0 )
    {
#ifdef DEBUG_LOAN
        printf("\n Here");
#endif                
        StringSetText(STRING_LOAN_TOTAL_PAYMENT_RESULT, (BYTE*)(""));
        StringDrawString(STRING_LOAN_TOTAL_PAYMENT_RESULT);
        StringSetText(STRING_LOAN_TOTAL_INTEREST_RESULT, (BYTE*)(""));
        StringDrawString(STRING_LOAN_TOTAL_INTEREST_RESULT);
        TextboxSetText((ObjectID)(calculating_item + TEXTBOX_LOAN_NUM_YEARS), (BYTE*)(""));
        TextboxDrawTextbox((ObjectID)(calculating_item + TEXTBOX_LOAN_NUM_YEARS));
        return FALSE;
    }
	
	
#ifdef DEBUG_LOAN
	printf("\n Here 1");
#endif                
	
	
    switch (calculating_item)
    {
	case NUM_YEARS:
		if (item_value[1])
		{
			temp = log((double)1 - (item_value[2] * item_value[1]/(double)100)/(double)12/item_value[3]);
			if (isinf(temp) || isnan(temp))
			{
				TextboxSetText(TEXTBOX_LOAN_NUM_YEARS, (BYTE*)(""));
				TextboxDrawTextbox(TEXTBOX_LOAN_NUM_YEARS);
				return FALSE;
			}
			temp1 = (double)(-12) * log((double)1 + item_value[1]/(double)12/(double)100);
			result = temp/temp1;
		}
		else result = item_value[2]/item_value[3]/(double)12;
		break;
	case INTEREST_RATE:
		result = Newton(item_value[0], item_value[3], item_value[2]);
		if (result != -1 && result < 0)
			result = 0;
		break;
	case LOAN_AMOUNT:
		if (item_value[1])
		{
			temp = (double)(-12) * item_value[0] * log((double)1 + item_value[1]/(double)100/(double)12);
			result = (double)12 * item_value[3] * (double)100 / item_value[1] * ((double)1 - exp(temp));
		}
		else result = item_value[0] * (double)12 * item_value[3];
		break;
	case MONTHLY_PAYMENT:
#ifdef DEBUG_LOAN
		printf("\n Monthly_payment");
#endif                    
		if (item_value[1])
		{
			temp = (double)(-12) * item_value[0] * log((double)1 + item_value[1]/(double)100/(double)12);
			result = item_value[2] * item_value[1] / (double)12 / (double)100 / ((double)1 - exp(temp));
		}
		else result = item_value[2]/item_value[0]/(double)12;
		break;
	default: break;
    }
	
#ifdef DEBUG_LOAN
    dtoa(item_value[0], debug, 20);
    printf("\n item_value[0] = %s", debug);
    dtoa(item_value[1], debug, 20);
    printf("\n item_value[1] = %s", debug);
    dtoa(item_value[2], debug, 20);
    printf("\n item_value[2] = %s", debug);
    dtoa(item_value[3], debug, 20);
    printf("\n item_value[3] = %s", debug);
    dtoa(result, debug, 20);
    printf("\n result = %s", debug);
#endif    
    
	
#ifdef PR31700
    if (isinf(result) || isnan(result) || result == -1.0)
    {
#ifdef DEBUG_LOAN
        printf("\n No Solution");
#endif        
        
        loan_error = LOAN_NO_SOLUTION;
        enter_form_id = FORM_LOAN;
        FormInitAllFormObjects(FORM_METRIC_OVERFLOW);
        FormPopupForm(FORM_METRIC_OVERFLOW);
        return FALSE;
    }
    else
    {
#endif
		for (i = 0; i < 4; i++)
		{
			if (i == calculating_item)
			{
				item_value[i] = result;
				break;
			}
		}
		
        if (item_value[1])
        {
            total_payment = item_value[3] * item_value[0] * (double)12;
            total_interest = total_payment - item_value[2];
        }
        else
        {
            total_payment = item_value[2];
            total_interest = 0.00;    
        }
#ifdef PR31700
    }  
#endif
	// end CALCULATION here !!!
    if (result > 999999999999.0 ||
        total_payment > 9999999999999.0 ||
        total_interest > 99999999999999.0)
    {
#ifdef DEBUG_LOAN
        printf("\n Out Of Range");
#endif        
        loan_error = LOAN_OUT_OF_RANGE;
        enter_form_id = FORM_LOAN;
        FormInitAllFormObjects(FORM_METRIC_OVERFLOW);
        FormPopupForm(FORM_METRIC_OVERFLOW);
        return FALSE;
    }       
	
#ifdef DEBUG
    printf("\n  === Put Total Payment Total Interest ===");
#endif
	
	item_value[calculating_item] = result;
	temp_text   = (BYTE*)qmalloc(50 * sizeof(BYTE));
	for (i = STRING_LOAN_TOTAL_PAYMENT_RESULT; i <= STRING_LOAN_TOTAL_INTEREST_RESULT; i++)
	{
        if (total_payment <= 0 || total_interest <= 0)
        {
            StringSetText(STRING_LOAN_TOTAL_PAYMENT_RESULT, (BYTE*)(""));
            StringDrawString(STRING_LOAN_TOTAL_PAYMENT_RESULT);
            StringSetText(STRING_LOAN_TOTAL_INTEREST_RESULT, (BYTE*)(""));
            StringDrawString(STRING_LOAN_TOTAL_INTEREST_RESULT);
            break;
        }
        if (i == STRING_LOAN_TOTAL_INTEREST)
            continue;
		if (i == STRING_LOAN_TOTAL_PAYMENT_RESULT)
			dtoa(total_payment, (char*)temp_text, 20);
		else  dtoa(total_interest, (char*)temp_text, 20);
		
#ifdef DEBUG
        printf("\n  Total Payment 1 = %s", temp_text);
#endif
		
        CalculatorChopDisplay(temp_text, 13, &source_text);
		
#ifdef DEBUG
        printf("\n  Total Payment 2 = %s", source_text);
#endif
		
		
		
		j = 0;
		while (source_text[j] != 0)
		{
			if (source_text[j] == '.')
			{
				found_decimal = TRUE;
				break;
			}
			j++;
		}
		
		
		if (found_decimal == TRUE)
		{
			j = strlen(source_text) - 1;
			while (source_text[j] == '0' && j >= 0)
			{
				source_text[j] = '\0';
				j--;
			}
		}
		
#ifdef DEBUG
        printf("\n  Total Payment 3 = %s", source_text);
#endif
		
        MetricAddZeroBehindDecimal(source_text, 2, 14, &output_string);
		
#ifdef DEBUG
        printf("\n  Total Payment 4 = %s", output_string);
#endif
		
        for (k = (strlen(output_string) - 1); k >= 0; k--)
        {
            if (output_string[k] == '.')
            {
                if (k <= (strlen(output_string) - 1 - 2))
                    output_string[k + 3] = 0;
                break;
            }
        }
		
#ifdef DEBUG
        printf("\n  Total Payment 5 = %s", output_string);
#endif
		
		StringSetText(i, output_string);
		StringDrawString(i);
		qfree(source_text);
		qfree(output_string);
	}
	
#ifdef DEBUG
    printf("\n  === Exit Total Payment Total Interest ===");
#endif
	
	
	for (i = TEXTBOX_LOAN_NUM_YEARS; i <= TEXTBOX_LOAN_MONTHLY_PAYMENT; i++)
	{
		if (calculating_item == (i - TEXTBOX_LOAN_NUM_YEARS))
		{
			dtoa(item_value[i - TEXTBOX_LOAN_NUM_YEARS], (char*)temp_text, 20);
			CalculatorChopDisplay(temp_text, 11, &source_text);
			j = strlen(source_text) - 1;
			while (source_text[j] == '0' && j >= 0)
			{
				source_text[j] = '\0';
				j--;
			}
			MetricAddZeroBehindDecimal(source_text, 2, 12, &output_string);
            for (k = (strlen(output_string) - 1); k >= 0; k--)
            {
                if (output_string[k] == '.')
                {
                    if (k <= (strlen(output_string) - 1 - 2))
                        output_string[k + 3] = 0;
                    break;
                }
            }
			TextboxSetText(i, output_string);
			TextboxDrawTextbox(i);
			qfree(source_text);
			qfree(output_string);
		}
		else
		{
			TextboxGetTextPointer(i, &textbox_text);
			strcpy(temp_text, textbox_text);
			CalculatorChopDisplay(temp_text, 12, &source_text);
			TextboxSetText(i, source_text);
			TextboxDrawTextbox(i);
			qfree(source_text);
		}
	}
	qfree(temp_text);
	return TRUE;
}

