﻿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));        
    }
}