﻿if (typeof (Tangora) == 'undefined') var Tangora = {};
Tangora.CalculationLibrary = new CalculationLibrary();

function CalculationLibrary()
{
	this._decimalSign = ",";
	this._thousandSeparator = ".";
	this._expressions = [];
	this._resolvers = [];

	this.formatNumber = function (value, numDecimals)
	{
		if (isNaN(value)) return value;
		if (value == '') return value;

		var snum = new String(value);
		var sec = snum.split('.');
		var whole = parseFloat(sec[0]);
		var result = '';

		if (sec.length > 1)
		{
			var dec = new String(sec[1]);
			dec = String(parseFloat(sec[1]) / Math.pow(10, (dec.length - numDecimals)));
			if (whole >= 0) dec = String(whole + Math.round(parseFloat(dec)) / Math.pow(10, numDecimals));
			else dec = String(whole - Math.round(parseFloat(dec)) / Math.pow(10, numDecimals));
			var dot = dec.indexOf('.');
			if (dot == -1 && numDecimals > 0)
			{
				dec += '.';
				dot = dec.indexOf('.');
			}
			while (dec.length <= dot + numDecimals) { dec += '0'; }
			result = dec;
		} else
		{
			var dot;
			var dec = new String(whole);
			if (numDecimals > 0)
			{
				dec += '.';
				dot = dec.indexOf('.');
				while (dec.length <= dot + numDecimals) { dec += '0'; }
			}
			result = dec;
		}
		return result;
	}

	this.addThousandSeparator = function (value)
	{
		var re = new RegExp('(-?[0-9]+)([0-9]{3})');

		while (re.test(value)) value = value.replace(re, '$1' + this._thousandSeparator + '$2');
		return value;
	}


	this.FormatValue = function (value, decimalsign, numdecimals, extended)
	{
		if (isNaN(value)) return value;
		value = new String(this.formatNumber(value, numdecimals)).replace('.', decimalsign);
		extended = true;
		if (extended) value = this.addThousandSeparator(value);
		return value;
	}

	this.removeFormatting = function (value)
	{
		var isValue = typeof (value) == 'object';
		value = new String(value);
		if (value.indexOf(this._decimalSign) > -1)
		{
			value = value.replace(this._decimalSign, '|');
		}
		if (isValue)
		{
			value = value.replace('.', '|');
		}
		var re = new RegExp('\\' + this._thousandSeparator, 'gi');
		value = value.replace(re, '');
		value = value.replace('|', '.');
		return this.toNumber(value);
	}

	this.toNumber = function (value)
	{
		return parseFloat(value, 10);
	}

	this.addResolver = function (name, callback)
	{
		this._resolvers[name] = callback;
	}

	this.addExpression = function (name, expr)
	{
		this._expressions[name] = expr;
	}

	this.execExpression = function (name, args)
	{
		var expr = this._expressions[name];
		var re = new RegExp("\{.*?\}", "");
		var mf = null;
		var realExpr = expr;
		mf = re.exec(expr);
		while (mf)
		{
			if (args && typeof (args[mf]) != 'undefined')
			{
				realExpr = realExpr.replace(mf, args[mf]);
			}
			else
			{
				var sMf = mf[0];
				var defValue = 0;
				if (mf[0].indexOf(',') > -1)
				{
					sMf = mf[0].split(',')[0] + '}';
					defValue = new Number(this.removeFormatting(mf[0].split(',')[1].replace('}', '')));
				}
				var value = 0;
				try
				{
					var resolver = this._resolvers[sMf];
					if (resolver) value = this.removeFormatting(resolver());
					else value = this.removeFormatting(this.execExpression(sMf.replace('{', '').replace('}', '')));
					if (isNaN(value)) value = defValue;
				}
				catch (e)
				{
					value = defValue;
				}
				realExpr = realExpr.replace(mf, value);
			}
			var rc = realExpr; //RegExp.rightContext;            
			mf = re.exec(rc);
		}
		return new Number(eval(realExpr));
	}
}
