var CostCalculator = function(global_settings){
	var settings = global_settings.engine;
	var self = this;
	
	this.metric = false;
	
	this.calculate = function(inputs){
		var res = {};
		var inpts = {}
		$.extend(inpts,inputs);
		
		inpts.poolSize = (Number(inpts.hasSpa) == 1) ?
			(inpts.poolSize + 12000)
			: inpts.poolSize
		;
		
		var std = calcStandard(inpts);
		var twoSpd = calcTwoSpeed(inpts);
		var varSpd = calcVarSpeed(inpts);
		$.extend(res,std,twoSpd,varSpd);
		return res;
	}
	
	this.setSystem = function(blnMetric, global_settings) {
		self.metric = blnMetric;
		settings = global_settings.engine;
	}
	
	
	function calcStandard(inpts){
		var res = {};
		
		//calculate flow rate
		var flowRate = settings.standardPump['_'+inpts.pumpHP][0];
		var demand = settings.standardPump['_'+inpts.pumpHP][1];
		
		//calculate turnovers per day
		res.stdTurnOvers = getTurnOversPerDay(flowRate,inpts.runTime,inpts.poolSize);
		
		//calculate hours running per day
		res.stdRunTime = getHoursPerDay(inpts.runTime,res.stdTurnOvers);
		res.stdRunTime = (res.stdRunTime > 24) ? 24 : res.stdRunTime;
		
		//ensure minimum of 1 turnover per day
		res.stdTurnOvers = (res.stdTurnOvers < 1) ? 1 : res.stdTurnOvers;
		
		//calculate cost of operation
		inpts.stdCostPerDay = inpts.electricCost * demand / 1000 * res.stdRunTime;
		res.stdCostPerDay = inpts.stdCostPerDay;
		res.stdCostPerYear = inpts.stdCostPerDay * 30.4 * inpts.monthsPerYear;
		return res;
	}
	
	function calcTwoSpeed(inpts){
		var res = {};
		
		var pumpData = getTwoSpeedData(inpts.poolSize,inpts.runTime);
		var lowSpeed = pumpData[0];
		var highSpeed = pumpData[1];
		
		var minHoursAtMax = settings.minimumHoursHighPumpSpeed;
		var minTurnOvers = settings.minimumTurnOversPerDay;
		
		var baseHoursAtLow = inpts.runTime - minHoursAtMax;
		
		var highTurnOversPerDay = highSpeed.flowRate * minHoursAtMax * 60 / inpts.poolSize;
		var altLow = (lowSpeed.flowRate * baseHoursAtLow * 60 ) / inpts.poolSize;
		var lowTurnOversPerDay = minTurnOvers - highTurnOversPerDay;
		lowTurnOversPerDay = (altLow > lowTurnOversPerDay) ? altLow : lowTurnOversPerDay;
		
		var lowFlowRate = inpts.poolSize * lowTurnOversPerDay / baseHoursAtLow / 60;
		lowFlowRate = (lowSpeed.flowRate > lowFlowRate) ? lowSpeed.flowRate : lowFlowRate;
		var adjFlowRate = (lowFlowRate > highSpeed.flowRate) ? highSpeed.flowRate : lowFlowRate;
		
		var lowRunTime = (lowTurnOversPerDay * inpts.poolSize / adjFlowRate / 60);
		res.twoSpdRunTime = minHoursAtMax + lowRunTime;
		res.twoSpdRunTime = (res.twoSpdRunTime > 24) ? 24 : res.twoSpdRunTime;
		
		//Curve A
		/*var lowDemand = 
			-0.002603 * Math.pow(adjFlowRate,3) 
			+ 0.5057 * Math.pow(adjFlowRate,2)
			+ 18.149 * adjFlowRate 
			- 591.82
		;*/
		
		//Curve C
		var lowDemand = 
			- 0.0053917 * Math.pow(adjFlowRate,3)
			+ 1.0814209 * Math.pow(adjFlowRate,2)
			- 28.45458 * adjFlowRate
			+ 130.253
		;
		
		var averageFlow = ( minHoursAtMax * highSpeed.flowRate + lowRunTime * adjFlowRate) / res.twoSpdRunTime;
		var averagePowerDemand = (minHoursAtMax * highSpeed.powerDemand + lowRunTime * lowDemand) / res.twoSpdRunTime;
		
		var powerUsage = 
			( 
				(minHoursAtMax * highSpeed.powerDemand) 
				+ (lowRunTime * lowSpeed.powerDemand) 
			) / res.twoSpdRunTime
		;
		res.twoSpdTurnOvers = averageFlow * res.twoSpdRunTime * 60 / inpts.poolSize;
		
		var costPerDay = inpts.electricCost * averagePowerDemand / 1000 * res.twoSpdRunTime;
		res.twoSpdSvngsPerDay = inpts.stdCostPerDay - costPerDay;
		res.twoSpdSvngsPerYear = res.twoSpdSvngsPerDay * 30.4 * inpts.monthsPerYear;
		
		res.twoSpdSvngsPct = res.twoSpdSvngsPerDay / inpts.stdCostPerDay * 100;
		
		return res;
	}
	
	function calcVarSpeed(inpts){
		var res = {};
		
		//calculate flow rate
		//var flowRate = getVariableFlowRate(inpts.poolSize,inpts.runTime);
		var flowRate = inpts.pumpSpeed / (self.metric ? 9.279 : 35.12);
		
		//calculate run time
		var adjFlowRate = getVariableFlowRate(inpts.poolSize,inpts.runTime);
		res.varSpdRunTime = ((inpts.poolSize / adjFlowRate) - (inpts.runTime * 60))/60 + inpts.runTime;
		res.varSpdRunTime = (res.varSpdRunTime > 24) ? 24 : res.varSpdRunTime;
		
		//calculate turnovers per day
		var turnOvers = getTurnOversPerDay(adjFlowRate, res.varSpdRunTime, inpts.poolSize);
		var adjTurnOvers = flowRate * 60 * res.varSpdRunTime / inpts.poolSize;
		res.varSpdRunTime = (adjTurnOvers<turnOvers) ? 
			(res.varSpdRunTime / adjTurnOvers)
			: (res.varSpdRunTime)
		;
		res.varSpdRunTime = (res.varSpdRunTime > 24) ? 24 : res.varSpdRunTime;
		res.varSpdTurnOvers = getTurnOversPerDay(flowRate, res.varSpdRunTime, inpts.poolSize);
		
		//calculate savings per day
		var equation = settings.variableSpeedPump.equation;
		var powerUsage = calcPowerUsage(flowRate, equation);
		var costPerDay = inpts.electricCost * powerUsage / 1000 * res.varSpdRunTime;
		res.varSpdSvngsPerDay = inpts.stdCostPerDay - costPerDay;
		
		//calculate savings per year
		res.varSpdSvngsPerYear = res.varSpdSvngsPerDay * 30.4 * inpts.monthsPerYear;
		
		//calculate savings percentage
		res.varSpdSvngsPct = res.varSpdSvngsPerDay / inpts.stdCostPerDay * 100;
		
		return res;
	}
	
	function getVariableFlowRate(poolSize,runTime){
		var reqFlow = (poolSize / (runTime * 60));
		var maxFlow = settings.variableSpeedPump.maxFlow;
		return (reqFlow > maxFlow) ? maxFlow : reqFlow;
	}
	
	function getTwoSpeedData(poolSize,runTime){
		var reqFlow = (poolSize/(runTime*60));
		var twoSpds = settings.twoSpeedPump;
		var pump = null;
		for(var i = 0; i < twoSpds.length; i++){
			if( reqFlow < twoSpds[i][0].flowRate ){
				pump = twoSpds[i];
				break;
			}
		}
		if(pump==null) pump = twoSpds[ twoSpds.length - 1 ];
		return pump;
	}
	
	function getTurnOversPerDay(flowRate, runTime, poolVolume){
		return flowRate * runTime * 60 / poolVolume;
	}
	
	function getHoursPerDay(runTime,turnOvers){
		var min = settings.minimumTurnOversPerDay;
		var hours = (turnOvers < min) ? (runTime / turnOvers) : runTime;
		return hours;
	}
	
	function calcPowerUsage(flowRate, equation){
		var result = 0;
		var cur = 1;
		for(var i = equation.length-1; i>=0; i--) {
			cur = cur * flowRate / (self.metric ? 3.785 : 1);
			result += equation[i] * cur;
		}
		return result;
	}
	
	this.defaultPumpSpeed = function(inpts){
		var flow = getVariableFlowRate(inpts.poolSize,inpts.runTime);
		var speed = flow * (self.metric ? 9.279 : 35.12);
		return (speed < 1000) ? 1000 : speed;
	}
	
	this.runTests = function(){
		var res = getTurnOversPerDay(73.50,8,52000);
		fireunit.ok(res.toFixed(3) == 0.678, "Calculate 0.678 turn overs per day: " + res);
		
		res = getHoursPerDay(8,0.678);
		fireunit.ok(res.toFixed(1) == 11.8, "Extend run time to 11.8 hours: " + res);
	}
};