

function fvCalculator(title)
{
	this.title = title;

	this.rows = new Array();
	
	this.fields = {};
	this.globals = {};
	
	this.masterFieldNames = new Array();

}


fvCalculator.prototype.addField = function(field, master)
{
	this.fields[field.name] = field;
	
	if (master)
		this.masterFieldNames.push(field.name);
}


fvCalculator.prototype.addGlobal = function(field, master)
{
	this.globals[field.name] = field;
/*	
	if (master)
		TODO: Implement master globals
*/
}


fvCalculator.prototype.addRow = function(title, form)
{
	this.rows.push(new fvRow(title, form, this.fields, this.masterFieldNames));
}


fvCalculator.prototype.addPreOp = function(button, callFunction)
{
	button.preOp = callFunction;
}

fvCalculator.prototype.addPostOp = function(button, callFunction)
{
	button.postOp = callFunction;
}

fvCalculator.prototype.enableButtons = function(form)
{
	// Enable calculate buttons
	for (field in this.fields)
	{
		if (form[field])
		{
			form[field].onclick = this.buttonClick(field, form[field].preOp, form[field].postOp);
		}
	}
	
	for (field in this.globals)
	{
		if (form[field])
		{
			form[field].onclick = this.buttonClick(field, form[field].preOp, form[field].postOp);
		}
	}
	
	
	// Enable row ready trackers
	for (var i = 0; i < this.rows.length; i++)
	{
		var rowReady = this.fieldEdit(this.rows[i]);
	
		for (field in this.fields)
		{
			this.fields[field].setChangeEvent(this.rows[i].form, rowReady);
		}
	}
}


fvCalculator.prototype.buttonClick = function(field, preOp, postOp)
{
	var calc = this;
	
	return function() {if(preOp) preOp(); calc.calculateField(field); if(postOp) postOp();};
}


fvCalculator.prototype.fieldEdit = function(row)
{
	return function(){row.setReady()};
}



fvCalculator.prototype.calculateField = function(fieldName)
{
	if(fieldName in this.fields)
	{
		for(var i = 0; i < this.rows.length; i++)
		{
			this.rows[i].calculateField(fieldName);
		}
	}
	
	
	if(fieldName in this.globals)
	{
		// Update masters on each row
		for(var i = 0; i < this.rows.length; i++)
		{
			this.rows[i].calculateField(null);
		}
	
		var valueListArray = new Array();
		
		for(var i=0; i<this.rows.length; i++)
		{
			valueListArray.push(this.rows[i].getValueList());
		}
		
		this.globals[fieldName].setValue(this.globals[fieldName].solve(valueListArray));	
	}
	
	// TODO: Update master globals here, when those exist
}



fvCalculator.prototype.calculateAll = function()
{
	for(var i=0; i<this.rows.length; i++)
	{
		this.rows[i].calculate();
	}
}

fvCalculator.calculateValue = function(data, goal, base, calculateBase, hint, digits)
{
	digits *= -1;

	data[goal] = hint;
	calculated = calculateBase(data);
	sign = (calculated > data[base]) ? -1 : 1;

	for (i = 0; i >= digits; i--)
	{
		while (sign * (data[base] - calculated) > 0)
		{
			data[goal] += sign * Math.pow(10,i);
			calculated = calculateBase(data);
		}
		
		data[goal] -= sign * Math.pow(10,i);
		calculated = calculateBase(data);
	}

	return data[goal];
}
