// we use this type of notation (JSON-notation) to let ourself later use static call of this class
var NumberHandler = {

	// public funcitons 
	
	numberFormat: function (string, type, positive, byModule) {
		if (positive) { string = Math.abs(string); }
		var point    = NUMBER_FORMAT_CONFIG['decimal_point'];
		var thousand = NUMBER_FORMAT_CONFIG['thousands_separator'];
		var decimals = NumberHandler.getDecimals(type);
		if (typeof byModule == 'undefined') { byModule = false; }
		
		if (parseFloat(Math.abs(string)) < 0.000000001) { string = 0; } // avoid of show '9,09e-13' not as '0.00'
		 
		return NumberHandler._numberFormat(string, decimals, point, thousand, byModule);
	},
	
	roundByType: function (value, type, byModule) {
		value = parseFloat(value);
		value +=(value < 0 ? -1: 1) * 0.00001; // this hack affect only values like 25.499999999 so after rounding we have 26, not 25. this required for js only because of wrong multiplying (e.g 1.255 * 100 = 125.4999999 not 125.5)
		var decimals = NumberHandler.getDecimals(type);
		if (decimals != null) {
			if (byModule) {
				if (value < 0) {
					var negative = true;
					value = Math.abs(value);
				}
			}
			var temp = Math.pow(10, decimals);
			value = Math.round(value * temp) / temp;
		}
		return negative ? value * -1 : value;
	},
	
	getLimit: function (type) {
		var decimals = NumberHandler.getDecimals(type);
		if (decimals != null) { var limit = 1.0 / Math.pow(10, decimals); } 
		return limit;
	},
	
	getDecimals: function (type) {
		if (type == 'accuracy_integer'){ return 0;}
		switch (type) {
			case 'fraction_0':
				return 0;
			case 'fraction_2':
				return 2;
			case 'fraction_4':
				return 4;
		}
		var key = (type == 'amount_sum'        || 
				   type == 'quantity_sum'      ||
				   
				   type == 'amount_details'    || 
				   type == 'quantity_details'  ||
				   
				   type == 'accuracy_amount'   || 
				   type == 'quantity_sum'      || 
				   type == 'accuracy_quantity' || 
				   
				   type == 'percentage' ||
				   type == 'rate_amount') ? (type + '_fraction') : ('amount_details_fraction');
		return NUMBER_FORMAT_CONFIG[key];
	},
	
	cutDecimals: function (number, decimals) { // used in InvoiceProductClasses - when calculate price interval by income price_with_vat
	// handle number in exponential notation
		var exponent  = "";
		var numberstr = number.toString();
		var eindex    = numberstr.indexOf("e");
		if (eindex > -1) { 
			exponent = numberstr.substring(eindex);
			number = parseFloat(numberstr.substring(0, eindex));
		}
		
		var sign       = (number < 0) ? "-" : "" ;
		var integer    = ( (number > 0) ? Math.floor(number) : Math.abs(Math.ceil(number)) ).toString();
		var fractional = number.toString().substring(integer.length + sign.length);
		    fractional = (decimals != null && decimals > 0 || fractional.length > 1) ? ('.' + fractional.substring(1)) : "";
		
		if (decimals != null && decimals > 0){
			for (var i = fractional.length - 1, z = decimals; i < z; ++i) {	fractional += "0";	}
		}
		
		return sign + integer + fractional + exponent;
	},
	
	// private funcitons
	
	_numberFormat: function (number, decimals, dec_point, thousands_sep, byModule) {
		var exponent  = "";

		var numberstr = number.toString();
		var eindex    = numberstr.indexOf("e");
		// handle number in exponential notation
		if (eindex > -1) { 
			exponent = numberstr.substring(eindex);
			number = parseFloat(numberstr.substring(0, eindex));
		}
		// round number if it is necessary
		if (decimals != null) { 
			var temp = Math.pow(10, decimals);
			number = parseFloat(number);
			number +=  (number < 0 ? -1: 1 ) * 0.00001; // this hack affect only values like 25.499999999 so after rounding we have 26, not 25. this required for js only because of wrong multiplying (e.g 1.255 * 100 = 125.4999999 not 125.5)
			if (byModule) {
				if (number < 0) {
					var negative = true;
					number = Math.abs(number);
				}
				number = Math.round(number * temp) / temp;
				if (negative) number *= -1;
			} else {
				number = Math.round(number * temp) / temp;
			}
		}
		// TODO: somebody, comment all these, please 
		var sign       = (number < 0) ? "-" : "" ;
		var integer    = ( (number > 0) ? Math.floor(number) : Math.abs(Math.ceil(number)) ).toString();
		var fractional = number.toString().substring(integer.length + sign.length);
		 	dec_point  = (dec_point != null)? dec_point : ".";
		    fractional = (decimals != null && decimals > 0 || fractional.length > 1) ? (dec_point + fractional.substring(1)) : "";
		
		if (decimals != null && decimals > 0){
			for (var i = fractional.length - 1, z = decimals; i < z; ++i) {	fractional += "0";	}
		}
		
		thousands_sep = (thousands_sep != dec_point || fractional.length == 0) ? thousands_sep : null;
		if (thousands_sep != null && thousands_sep != ""){
			for (var i = integer.length - 3; i > 0; i -= 3){
				integer = integer.substring(0 , i) + thousands_sep + integer.substring(i);
			}
		}
		return sign + integer + fractional + exponent;
	},
	
	handleAccuracy: function (contact_id) {
	/*
		NB! function should be called before you will use 'amount_sum' for round or format amounts!! 
		NB! to use this function, add this to .sma
		
		{load_js_data name="CONTACT_CURRENCY_LIST"|upper table="contact" method="getContactCurrencyComboboxList" params=$contactType}
		{load_js_data name="LOCAL_CURRENCY_NUMBER_FORMAT_CONFIG" table="config" method="getLocalCurrencyNumberFormats"}
		{load_js_data name="NON_LOCAL_CURRENCY_NUMBER_FORMAT_CONFIG" table="config" method="getNonLocalCurrencyNumberFormats"}
	*/	
		if (typeof CONTACT_CURRENCY_LIST == 'undefined' || 
			typeof NUMBER_FORMAT_CONFIG == 'undefined' ||
			typeof LOCAL_CURRENCY_NUMBER_FORMAT_CONFIG == 'undefined' || 
			typeof NON_LOCAL_CURRENCY_NUMBER_FORMAT_CONFIG == 'undefined') {
			return false;	
		}
		
		var is_local   = true;		
		var contact_id = parseInt(contact_id);
		for (var i = 0; i < CONTACT_CURRENCY_LIST.length; i++) {
			if (CONTACT_CURRENCY_LIST[i].id == contact_id) {
				if (CONTACT_CURRENCY_LIST[i].is_default == 0) { // .is_default = 1 or 0
					is_local = false;
				}
			}
		}
		NUMBER_FORMAT_CONFIG = is_local ? LOCAL_CURRENCY_NUMBER_FORMAT_CONFIG : NON_LOCAL_CURRENCY_NUMBER_FORMAT_CONFIG;
		return true;  	 
	}
};