#import "Anuity.h"
#include <math.h>

@implementation Anuity

double doubleFactorOf(double c, double factor)
{
    int va = (c / factor);
    return ((double) va) * factor;
}

- (void)awakeFromNib
{
	[capitalSlide setAltIncrementValue:1000.0];
	[tauxSld setAltIncrementValue:0.05];
	[dureeSld setAltIncrementValue:0.5];
	[pmntSld setAltIncrementValue: 5.0];
}

- (void)chmtMatrixDidChange:(id)sender
{
}

- (void)periodeDidChange:(id)sender
{
    [self updateValue];
}

- (void)slideDidChange:(id)sender
{
}

- (void)txtDidChange:(id)sender
{
}


- (void)updatedCapitalTxt:(id)sender
{
    double c = [sender doubleValue];
    c = doubleFactorOf(c, 100.0);
    [capitalSlide setDoubleValue:c];
    [self updateValue];
}

- (void)updatedTauxTxt:(id)sender
{
    [tauxSld takeDoubleValueFrom:sender];
    [self updateValue];
}

- (void)updatedDureeTxt:(id)sender
{
	[dureeSld takeStringValueFrom:sender];
	[self updateValue];
}

- (void)updatedPmntTxt:(id)sender
{
	[pmntSld takeStringValueFrom:sender];
	[self updateValue];
}

- (void)updatedCapitalSld:(id)sender
{
    double c = [sender doubleValue];
    c = doubleFactorOf(c, 100.0);
    [capitalTxt setDoubleValue:c];
    [self updateValue];
}

- (void)updatedTauxSld:(id)sender
{
    double c = [sender doubleValue];
    c = doubleFactorOf(c, 0.05);
    [tauxTxt setDoubleValue:c];
    [self updateValue];
}

- (void)updatedDureeSld:(id)sender
{
    double c = [sender doubleValue];
    c = doubleFactorOf(c, 0.5);
    [dureeTxt setDoubleValue:c];
    [self updateValue];
}

- (void)updatedPmntSld:(id)sender
{
    double c = [sender doubleValue];
    c = doubleFactorOf(c, 5.0);
    [pmntTxt setDoubleValue:c];
    [self updateValue];
}

double 
tryTaux(double capital, double duree, double pmnt, double m, double tx);

double 
tryTaux(double capital, double n, double pmnt, double m, double i)
{
    double tx = i / m;
    double term = pmnt * (1.0-pow(1.0+tx,n*m*-1.0))/tx;
    double fi = capital - term;
    double fii = 0.0, ni = 0.0;

    if(fabs(fi) < 10.0)
	return i;

    fii = pmnt * ((i*n*pow(1.0+tx, (-n*m)-1.0)) - (1.0 - pow(1.0+tx, -m*n))) / (i*tx);
    ni = fi / fii ;
    return tryTaux(capital, n, pmnt, m, i + ni);
}

- (void)updateValue
{
    double capital = [capitalTxt doubleValue];
    double duree = [dureeTxt doubleValue];
    double pmnt = [pmntTxt doubleValue];
    double taux = [self tauxNormalise];
    double m = [self m];
    double tx = taux/m;

    int tag = [[chmtMatrix selectedCell] tag];

    switch(tag)
        {
        case 0 : // ajustement du capital
          {
              capital = pmnt * (1.0-pow(1.0+tx,duree*m*-1.0))/tx;
              [capitalTxt setFloatValue:capital];
              [capitalSlide setFloatValue:capital];
              break;
          }
	case 1 : // ajustement du taux
	  {
	      double t = 0.0;
	      taux = tryTaux(capital, duree, pmnt, m, taux);
	      t = 100.0 * [self tauxSemestrielFromNormalise:taux];
	      [tauxTxt setFloatValue:t];
	      [tauxSld setFloatValue:t];
	      break;
	  }

	case 2 : // ajustement de la duree
	 {
             double base = 1.0+tx;
             double valu = -(( ( capital * tx ) / pmnt ) - 1.0);
	     double lg1 = log(valu);
	     double lg2 = log(base);
	     duree = -lg1 / (lg2*m);

             [dureeTxt setDoubleValue:duree];
             [dureeSld setDoubleValue:duree];
             break;
         }

	case 3 : // ajustement du paiement
	 {
             pmnt = capital/( (1-pow(1+tx,duree*[self m]*-1))/tx);
             [pmntTxt setFloatValue:pmnt];
             [pmntSld setFloatValue:pmnt];
             break;
         }
	default:
            break;
            }

    [futurValueTxt setDoubleValue:duree*m*pmnt];
}

- (double)m
{
	int tag = [[periodeSld selectedCell] tag];
	switch(tag)
	{
	case 0:
		return 12.0;
		break;
	case 1:
		return 26.2;
		break;
	case 2:
		return 52.4;
		break;
	default:
		return 12.0;
	}
        return 12.0;
}

- (double)tauxSemestrielFromNormalise:(double) i
{
    double m = [self m];
    return 2.0*(pow(1.0+(i/m), m/2.0)-1.0);
}

- (double)tauxNormalise
{
    double m = [self m];
    return m*(pow(1.0+([tauxTxt doubleValue]/200.0),2.0/m)-1.0);
}

/*
  - (void)report:(id)sender
{
    NSMutableString *report = @"Report of god !\r";
    [report appendWithFormat:@"Capital : %f $\r Taux : %f\%\r duree : "];

    return;
}
*/


@end
