/*

 This file is used both in the iPhone app and in the Test page

 var AH = Ah();

 Errors persist so create a new object if you get an error.

*/

/*
// TODO - clash of generic functions with common.js - should these go in the iphone common / factory js?

// Misc formatting / cleaning functions
function formatCurrency(n) {
	// remove sign and comma
	n = n.toString().replace(/£|,/g, '');
	if (isNaN(n)) {
		n = "0";
	}
	sign = (n == (n = Math.abs(n)));
	// round up
	n = Math.floor(n * 100 + 0.50000000001);
	n = Math.floor(n / 100).toString();
	for (var i = 0; i < Math.floor((n.length - (1 + i)) / 3); i++) {
		n = n.substring(0, n.length - (4 * i + 3)) + ',' + n.substring(n.length - (4 * i + 3));
	}
	return (((sign) ? '': '-') + n);
}


function stripCurrency(n) {
	if (!n) {
		n = 0;
	}
	n = n.toString().replace(/$|£|,|s|%/g, '');
	n = parseFloat(n);
	return n;

}
*/
function priceOut(value) {
	// remove any existing formatting, then reformat
	return "£" + formatCurrency(stripCurrency(value));
}

function toDecimal(n) {
	return Math.round(n * 100) / 100;
}

function Ah() {
	this.results = {};

	// Error handleing
	this.set_error = function(msg) {
		if (!this.error) {
			// only ever want the first error
			this.error = msg;
		}
	};

	this.get_error = function(msg) {
		if (this.error) {
			return this.error;
		}
	};

	this.has_error = function() {
		if (this.get_error()) {
			return 1;
		}
	};
	
	// TODO added
	this.clear_errors = function(){
		delete this.error;
	}
	
	this.alert_error = function() {
		if (this.has_error()) {
			show_msg(this.get_error());
			return 1;
		}
	};

	// Validation
	this.test_and_clean_number = function(n, field_name) {
		var errorMsg;
		if (n == '' || n == undefined ) {
			this.set_error("Please set " + field_name);
		} else {
			n = stripCurrency(n);
			if (isNaN(n)) {
				this.set_error("Please use numbers for " + field_name);
			//} else if(n == 0) {
		 // TODO - 0 shouldn't error on app2 as valid
			  //this.set_error("Please set a value for " + field_name);			
			}
		}
		if (!this.has_error()) {
			return n;
		}
	};
};

// Specific functions

Ah.prototype.calculateMinRentDeposit = function(val) {
	// TODO add error handling to val as breaks if not all numbers
	var val = this.test_and_clean_number(val, 'property value');
	if(this.has_error()) {
		return 0;
	}
	var min_deposit = Math.round((val / 100) * 25);
	return toDecimal(min_deposit);
};

Ah.prototype.calculateInterestOnly = function(loan, years, rate) {
	if (!loan) {
		this.set_error('Must have a loan greater than 0');
		return;
	};
	if (!years) {
		this.set_error('Must have a rate greater than 0');
		return;
	};
	if (!rate) {
		this.set_error('Must have more than 0 years');
		return;
	};

	var interest_only = ((loan * years) * (rate / 100)) / (12 * years);
	return toDecimal(interest_only);
};

Ah.prototype.calculateRepayment = function(loan, years, rate) {
	if (!loan) {
		this.set_error('Must have a loan greater than 0');
		return;
	};
	if (!years) {
		this.set_error('Must have a rate greater than 0');
		return;
	};
	if (!rate) {
		this.set_error('Must have more than 0 years');
		return;
	};
	var per_month = rate / 1200;
	var p = Math.pow(1 + per_month, (years * 12));
	var repay = loan / ((1 - (1 / p)) / per_month);
	return toDecimal(repay);
};

/*
	Calaulcate rental income
	-------------------------
	// TODO changed property_value to propertyValue through this function for consistency
	
	if(AH.calculateRent({
		property_value : property_value, // required
		deposit : deposit // optional
	})) {
		results = AH.results;
		results.rent;
		results.deposit; // set to min_deposit if not enough!
		results.min_deposit;
	} else {
		AH.alert_error();
	}
			
*/

Ah.prototype.calculateRent = function(conf) {

	var results = this.results;
	
	var val = this.test_and_clean_number(conf.property_value, 'property value');
	
	// TODO have added error checking on deposit field as can calc with empty field at mo
	var deposit = this.test_and_clean_number(conf.deposit, 'deposit');
	
	
	// errors on inputs?
	if(this.has_error()) {
		return 0;
	}
	
	
	var min_deposit = this.calculateMinRentDeposit(val);
	results.min_deposit = min_deposit;
	results.deposit = toDecimal(deposit);
	
	// TODO rearranged to work for an empty string as well as 0
	if (deposit < min_deposit) {	// else if user has entered 0 deposit, error
		this.set_error("Your deposit must be at least 25% (£" + formatCurrency(min_deposit) + ") of the property price.");
		return 0;
	}else if (!deposit){ // if user not entered deposit yet set to min deposit
		deposit = min_deposit;
		results.deposit = toDecimal(deposit);
		this.info = "The minimum deposit of 25% (£" + formatCurrency(min_deposit) + ") has been set automatically";
	}

	// all ok - lets calc!
	var r = 6 / 100;
	var rent = (val - deposit) * r / 12;
	if (rent < 0) {
		rent = 0;
	}
	
	results.rent = toDecimal(rent);

	return 1;

};


/*
	remortageSavings()
	
	Calculate the savings between two mortgages (based on rates)
	
	var AH = new Ah();	

	if(AH.remortageSavings({
		loanBalance		 : test.loan,
		currentInterestRate : test.current_rate,
		newInterestRate	 : test.new_rate,
		yearsLeft		   : test.years
	})) {
		var results = AH.results;
	
	} else {
		AH.alert_error();
	}

*/

Ah.prototype.remortageSavings = function(conf) {

	var results = this.results;

	var loan = this.test_and_clean_number(conf.loanBalance, 'loan amount');
	var mortgage_rate = this.test_and_clean_number(conf.currentInterestRate, 'current rate');
	var mortgage_rate_new = this.test_and_clean_number(conf.newInterestRate, 'new rate');
	var mortgage_years = stripCurrency(conf.yearsLeft);

	if(this.has_error()) {
		return 0;
	}

	// interest only
	results.interestOnlyCurrent = this.calculateInterestOnly(
										loan, mortgage_years, mortgage_rate);

	results.interestOnlyNew = this.calculateInterestOnly(
										loan, mortgage_years, mortgage_rate_new);

	results.interestOnlyDiff = toDecimal(results.interestOnlyCurrent - results.interestOnlyNew);

	// repayment
	results.repaymentCurrent = this.calculateRepayment(
										loan, mortgage_years, mortgage_rate);

	results.repaymentNew = this.calculateRepayment(
										loan, mortgage_years, mortgage_rate_new);

	results.repaymentDiff = toDecimal(results.repaymentCurrent - results.repaymentNew);

	return 1;

};

/*
	calcMortgageMonthlyPayments()
	
	Work out how much you have to pay each month
	
	var AH = new Ah();	

	if(AH.calcMortgageMonthlyPayments({
		loanBalance		 : test.loan,
		interestRate : test.current_rate,
		yearsLeft		   : test.years,
		overPayment : test.overpayment // optional
	})) {
		var results = AH.results;
		results.interestOnly;
		results.repayment;
		results.last_payment_month;
	
		var timeline = results.timeline;
		for(var i = 0; i < results.timeline.size; i++) {
			var month = timeline[i];
			month.remainingBalance;
			month.repayment;
		}
		
		// extract timeline data in format that works for flot.js
		var plot_data = AH.timelineToPlot();
		
	
	} else {
		AH.alert_error();
	}
	
*/

Ah.prototype.calcMortgageMonthlyPayments = function(conf) {


	var results = this.results;

	var loan = this.test_and_clean_number(conf.loanBalance, 'loan amount');
	var mortgage_rate = this.test_and_clean_number(conf.interestRate, 'current rate');
	var mortgage_years = stripCurrency(conf.yearsLeft);
	var overPay = stripCurrency(conf.overPayment);

	if(this.has_error()) {
		return 0;
	}

	// interest only for first month
	results.interestOnly = this.calculateInterestOnly(
										loan, mortgage_years, mortgage_rate);

	// repayment for first month
	results.repayment = this.calculateRepayment(
										loan, mortgage_years, mortgage_rate);



	var monthly_interest_rate = mortgage_rate / 1200;

	var months = mortgage_years * 12;
	// assume full term unless overrulled
	results.last_payment_month = months;

	var per_month_payment = results.repayment + overPay;

	var timeline = [];

	for(var i = 0; i < months; i++) {
		if(loan != 0) {
			var interest = (loan - overPay) * monthly_interest_rate;
			loan += interest;
			
			if(loan <= per_month_payment) {
				per_month_payment = loan;
				results.last_payment_month = i;
			}

			loan -= per_month_payment;							
		} else {
			per_month_payment = 0;
		}
		
		timeline[i] = {
			remainingBalance : toDecimal(loan),
			repayment : toDecimal(per_month_payment)
		};

	}
	results.timeline = timeline;
	
	return 1;

};

/*
	timelineToPlot()
	
	After calcMortgageMonthlyPayments() is called this can be
	called to return the results.timeline data in a format which
	works with flot.js. This is an Array of Arrays, each element
	being the key/value 

*/

Ah.prototype.timelineToPlot = function(conf) {

	var results = this.results;

	var balance = [];
	var num_payments = results.timeline.length;
	for(var i = 0; i < num_payments; i++) {
		if(results.timeline[i].remainingBalance) {
			var node = [i/12, results.timeline[i].remainingBalance];
			balance.push(node);			
		}
	}			
	return balance;			
};


/*
	howMuchCanIBorrow()
	
	Work out how much someone can borrow as a mortgage
	
	var AH = new Ah();	

	if(AH.howMuchCanIBorrow({
		app1 : app1, // required
		app2 : app2  // optional
	})) {
		var results = AH.results;
		results.maxBorrow;
	
	} else {
		AH.alert_error();
	}
	
*/

Ah.prototype.howMuchCanIBorrow = function(conf) {

	var app1 = 0;
	var app2 = 0;
	// TODO - added annual as should always match field names
	app1 = this.test_and_clean_number(conf.app1, "applicant one's annual income");

	if (conf.app2) {
		app2 = this.test_and_clean_number(conf.app2, "applicant two's annual income");
	}
	if(this.has_error()) {
		return 0;
	}

	var jointIncome = Number(app1) + Number(app2);
	var multiplier = 5;
	if(jointIncome >= 50000) {
		multiplier = 6;
	}
	
	this.results.maxBorrow = toDecimal(jointIncome * multiplier);

	return 1;

};

/*
	buyToLetHowMuchCanIBorrow()
	
	Work out how much someone can borrow as a mortgage
	
	var AH = new Ah();	

	if(AH.buyToLetHowMuchCanIBorrow({
		rent : rent, // required
		property_value : property_value  // optional
	})) {
		var results = AH.results;
		results.maxBorrow;
	
	} else {
		AH.alert_error();
	}
	
*/

Ah.prototype.buyToLetHowMuchCanIBorrow = function(conf) {

	var rent = stripCurrency(conf.rent, "monthly rental");
	var property_value = stripCurrency(conf.property_value, "property value");

	if(!rent && !property_value) {
		this.set_error("Please supply either the rent or property value");
		return 0;
	}
	
	var max_for_rent = 0;
	var max_for_property_value = 0;
	var max = 0;

	if(property_value) {
		max_for_property_value = (property_value/100)*75;
		max = max_for_property_value;
	}
	if(rent) {
		max_for_rent = (rent*12)/6*100;
		max = max_for_rent;
	}
	if(rent && property_value) {
		// find which ever is least
		max = max_for_property_value < max_for_rent ? 
						max_for_property_value : max_for_rent;
	}

	this.results.maxBorrow = toDecimal(max);

	return 1;

};

