// NameValueCollectionConverter
if(typeof Data == "undefined") Data={};

Data.NameValueCollection = function(items) {
	this.__type = "System.Collections.Specialized.NameValueCollection";
	this.keys = [];
	this.values = [];

	if(items != null && !isNaN(items.length)) {
		for(var i=0; i<items.length; i++)
			this.add(items[i][0], items[i][1]);
	}
}
Object.extend(Data.NameValueCollection.prototype, {
	add: function(k, v) {
		if(k == null || k.constructor != String || v == null || v.constructor != String)
			return -1;
		this.keys.push(k);
		this.values.push(v);
		return this.values.length -1;
	},
	containsKey: function(key) {
		for(var i=0; i<this.keys.length; i++)
			if(this.keys[i] == key) return true;
		return false;
	},
	getKeys: function() {
		return this.keys;
	},
	getValue: function(k) {
		for(var i=0; i<this.keys.length && i<this.values.length; i++)
			if(this.keys[i] == k) return this.values[i];
		return null;
	},
	setValue: function(k, v) {
		if(k == null || k.constructor != String || v == null || v.constructor != String)
			return -1;
		for(var i=0; i<this.keys.length && i<this.values.length; i++) {
			if(this.keys[i] == k) this.values[i] = v;
			return i;
		}
		return this.add(k, v);
	},
	toJSON: function() {
		return AjaxPro.toJSON({__type:this.__type,keys:this.keys,values:this.values});
	}
}, true);

// DataSetConverter
if(typeof Data == "undefined") Data={};

Data.DataSet = function(t) {
	this.__type = "System.Data.DataSet,System.Data";
	this.Tables = [];
	this.addTable = function(t) {
		this.Tables.push(t);
	}
	if(t != null) {
		for(var i=0; i<t.length; i++) {
			this.addTable(t[i]);
		}
	}
}

// DataTableConverter
if(typeof Data == "undefined") Data={};

Data.DataTable = function(c, r) {
	this.__type = "System.Data.DataTable,System.Data";
	this.Columns = [];
	this.Rows = [];
	this.addColumn = function(name, type) {
		this.Columns.push({Name:name,__type:type});
	}
	this.toJSON = function() {
		var dt = {};
		dt.Columns = [];
		for(var i=0; i<this.Columns.length; i++)
			dt.Columns.push([this.Columns[i].Name, this.Columns[i].__type]);
		dt.Rows = [];
		for(var i=0; i<this.Rows.length; i++) {
			var row = [];
			for(var j=0; j<this.Columns.length; j++)
				row.push(this.Rows[i][this.Columns[j].Name]);
			dt.Rows.push(row);
		}
		return AjaxPro.toJSON(dt);
	}
	this.addRow = function(row) {
		this.Rows.push(row);
	}
	if(c != null) {
		for(var i=0; i<c.length; i++)
			this.addColumn(c[i][0], c[i][1]);
	}
	if(r != null) {
		for(var i=0; i<r.length; i++) {
			var row = {};
			for(var c=0; c<this.Columns.length && c<r[i].length; c++)
				row[this.Columns[c].Name] = r[i][c];
			this.addRow(row);
		}
	}
}

// ProfileBaseConverter
if(typeof Data == "undefined") Data={};

Data.Profile = function() {
	this.toJSON = function() {
		throw "Data.Profile cannot be converted to JSON format.";
	}
	this.setProperty_callback = function(res) {
	}
	this.setProperty = function(name, object) {
		this[name] = object;
		AjaxPro.Services.Profile.SetProfile({name:o}, this.setProperty_callback.bind(this));
	}
}

// IDictionaryConverter
if(typeof Data == "undefined") Data={};

Data.Dictionary = function(type,items) {
	this.__type = type;
	this.keys = [];
	this.values = [];

	if(items != null && !isNaN(items.length)) {
		for(var i=0; i<items.length; i++)
			this.add(items[i][0], items[i][1]);
	}
}
Object.extend(Data.Dictionary.prototype, {
	add: function(k, v) {
		this.keys.push(k);
		this.values.push(v);
		return this.values.length -1;
	},
	clear: function()
	{
	    this.keys = [];
	    this.values = [];
	},
	count: function()
	{
	    return this.keys.length;
	},
	containsKey: function(key) {
		for(var i=0; i<this.keys.length; i++)
			if(this.keys[i] == key) return true;
		return false;
	},
	getKeys: function() {
		return this.keys;
	},
	getValue: function(key) {
		for(var i=0; i<this.keys.length && i<this.values.length; i++)
			if(this.keys[i] == key) return this.values[i];
		return null;
	},
	getValueByIndex: function(index) {
	    return this.values[index];
	},
	setValue: function(k, v) {
		for(var i=0; i<this.keys.length && i<this.values.length; i++) {
			if(this.keys[i] == k) this.values[i] = v;
			return i;
		}
		return this.add(k, v);
	},
	remove: function(key)
	{
	    var indexToRemove = this.getValue(key);
	    
	    for(var i = 0; i < this.keys.length; i++)
	    {
	        if(this.keys[i] == key)
	        {
	            indexToRemove = i;
	            break;
            }
	    }   
	    
	    if(indexToRemove)
        {
            this.keys.splice(indexToRemove, 1);
	        this.values.splice(indexToRemove, 1);
	    }
	},
	toJSON: function() {
		return AjaxPro.toJSON({__type:this.__type,keys:this.keys,values:this.values});
	}
}, true);


// Decimal
var Decimal = Class.create();

Object.extend(Decimal.prototype, {

	initialize: function(num, inputDecimal) 
	{
		this.COMMA = ',';
		this.PERIOD = '.';
		this.DASH = '-'; 
		this.LEFT_PAREN = '('; 
		this.RIGHT_PAREN = ')'; 
		this.LEFT_OUTSIDE = 0; 
		this.LEFT_INSIDE = 1;  
		this.RIGHT_INSIDE = 2;  
		this.RIGHT_OUTSIDE = 3;  
		this.LEFT_DASH = 0; 
		this.RIGHT_DASH = 1; 
		this.PARENTHESIS = 2; 
		this.NO_ROUNDING = -1 
		this.num;
		this.numOriginal;
		this.hasSeparators = false;  
		this.separatorValue;  
		this.inputDecimalValue; 
		this.decimalValue;  
		this.negativeFormat; 
		this.negativeRed; 
		this.hasCurrency;  
		this.currencyPosition;  
		this.currencyValue;  
		this.places;
		this.roundToPlaces; 
		this.truncate; 
		
		if (inputDecimal == null) 
		{
			this.setNumber(num, this.PERIOD);
		} 
		else 
		{
			this.setNumber(num, inputDecimal); 
		}
		
		this.setCommas(true);
		this.setNegativeFormat(this.LEFT_DASH); 
		this.setNegativeRed(false); 
		this.setCurrency(false); 
		this.setCurrencyPrefix('$');
		this.setPlaces(2);
	},
	
	setInputDecimal: function(val)
	{
		this.inputDecimalValue = val;
	},
	
	setNumber: function(num, inputDecimal)
	{
		if (inputDecimal != null) 
		{
			this.setInputDecimal(inputDecimal); 
		}
		this.numOriginal = num;
		this.num = this.justNumber(num);
	},
	
	toUnformatted: function()
	{
		return (this.num);
	},
	
	getOriginal: function()
	{
		return (this.numOriginal);
	},
	
	setNegativeFormat: function(format)
	{
		this.negativeFormat = format;
	},
	
	setNegativeRed: function(isRed)
	{
		this.negativeRed = isRed;
	},
	
	setSeparators: function(isC, separator, decimal)
	{
		this.hasSeparators = isC;
		if (separator == null) separator = this.COMMA;
		if (decimal == null) decimal = this.PERIOD;
		if (separator == decimal) 
		{
			this.decimalValue = (decimal == this.PERIOD) ? this.COMMA : this.PERIOD;
		} 
		else 
		{
			this.decimalValue = decimal;
		}
		this.separatorValue = separator;
	},
	
	setCommas: function(isC)
	{
		this.setSeparators(isC, this.COMMA, this.PERIOD);
	},
	
	setCurrency: function(isC)
	{
		this.hasCurrency = isC;
	},
	
	setCurrencyValue: function(val)
	{
		this.currencyValue = val;
	},
	
	setCurrencyPrefix: function(cp)
	{
		this.setCurrencyValue(cp);
		this.setCurrencyPosition(this.LEFT_OUTSIDE);
	},
	
	setCurrencyPosition: function(cp)
	{	
		this.currencyPosition = cp
	},
	
	setPlaces: function(p, tr)
	{
		this.roundToPlaces = !(p == this.NO_ROUNDING); 
		this.truncate = (tr != null && tr); 
		this.places = (p < 0) ? 0 : p; 
	},
	
	addSeparators: function(nStr, inD, outD, sep)
	{
		nStr += '';
		var dpos = nStr.indexOf(inD);
		var nStrEnd = '';
		if (dpos != -1) 
		{
			nStrEnd = outD + nStr.substring(dpos + 1, nStr.length);
			nStr = nStr.substring(0, dpos);
		}
		var rgx = /(\d+)(\d{3})/;
		while (rgx.test(nStr)) 
		{
			nStr = nStr.replace(rgx, '$1' + sep + '$2');
		}
		return nStr + nStrEnd;
	},
	
	toFormatted: function(ignoreSign)
	{	
		var pos;
		var nNum = this.num; 
		var nStr;            
		var splitString = new Array(2);  
		
		if (this.roundToPlaces) 
		{
		    var bHasSign = (nNum < 0);
		    
		    if(ignoreSign)
		        nNum = Math.abs(nNum);
		        
			nNum = this.getRounded(nNum);
			nStr = this.preserveZeros(Math.abs(nNum)); 
			
			if(ignoreSign && bHasSign)
			    nNum = nNum * -1;
		}
		else
		{
			nStr = this.expandExponential(Math.abs(nNum)); 
		}
		
		if (this.hasSeparators) 
		{
			nStr = this.addSeparators(nStr, this.PERIOD, this.decimalValue, this.separatorValue);
		} 
		else
		{
			nStr = nStr.replace(new RegExp('\\' + this.PERIOD), this.decimalValue); 
		}
		
		var c0 = '';
		var n0 = '';
		var c1 = '';
		var n1 = '';
		var n2 = '';
		var c2 = '';
		var n3 = '';
		var c3 = '';
		var negSignL = (this.negativeFormat == this.PARENTHESIS) ? this.LEFT_PAREN : this.DASH;
		var negSignR = (this.negativeFormat == this.PARENTHESIS) ? this.RIGHT_PAREN : this.DASH;
		
		if (this.currencyPosition == this.LEFT_OUTSIDE) 
		{
			if (nNum < 0) 
			{
				if (this.negativeFormat == this.LEFT_DASH || this.negativeFormat == this.PARENTHESIS) n1 = negSignL;
				if (this.negativeFormat == this.RIGHT_DASH || this.negativeFormat == this.PARENTHESIS) n2 = negSignR;
			}
			if (this.hasCurrency) c0 = this.currencyValue;
		} 
		else 
		if (this.currencyPosition == this.LEFT_INSIDE) 
		{
			if (nNum < 0) 
			{
				if (this.negativeFormat == this.LEFT_DASH || this.negativeFormat == this.PARENTHESIS) n0 = negSignL;
				if (this.negativeFormat == this.RIGHT_DASH || this.negativeFormat == this.PARENTHESIS) n3 = negSignR;
			}
			if (this.hasCurrency) c1 = this.currencyValue;
		}
		else if (this.currencyPosition == this.RIGHT_INSIDE) 
		{
			if (nNum < 0) 
			{
				if (this.negativeFormat == this.LEFT_DASH || this.negativeFormat == this.PARENTHESIS) n0 = negSignL;
				if (this.negativeFormat == this.RIGHT_DASH || this.negativeFormat == this.PARENTHESIS) n3 = negSignR;
			}
			if (this.hasCurrency) c2 = this.currencyValue;
		}
		else if (this.currencyPosition == this.RIGHT_OUTSIDE) 
		{
			if (nNum < 0) 
			{
				if (this.negativeFormat == this.LEFT_DASH || this.negativeFormat == this.PARENTHESIS) n1 = negSignL;
				if (this.negativeFormat == this.RIGHT_DASH || this.negativeFormat == this.PARENTHESIS) n2 = negSignR;
			}
			if (this.hasCurrency) c3 = this.currencyValue;
		}
		nStr = c0 + n0 + c1 + n1 + nStr + n2 + c2 + n3 + c3;
		
		if (this.negativeRed && nNum < 0) 
		{
			nStr = '<font color="red">' + nStr + '</font>';
		}
		
		return (nStr);
	},
	
	toPercentage: function()
	{
		nNum = this.num * 100;
		nNum = this.getRounded(nNum);
		return nNum + '%';
	},

	getZeros: function(places)
	{
		var extraZ = '';
		var i;
		for (i = 0; i < places; i++) 
		{
			extraZ += '0';
		}
		return extraZ;
	},
	
	expandExponential: function(origVal)
	{
		if (isNaN(origVal)) return origVal;
		
		var newVal = parseFloat(origVal) + ''; 
		var eLoc = newVal.toLowerCase().indexOf('e');
		
		if (eLoc != -1) 
		{
			var plusLoc = newVal.toLowerCase().indexOf('+');
			var negLoc = newVal.toLowerCase().indexOf('-', eLoc); 
			var justNumber = newVal.substring(0, eLoc);

			if (negLoc != -1) 
			{
				var places = newVal.substring(negLoc + 1, newVal.length);
				justNumber = this.moveDecimalAsString(justNumber, true, parseInt(places));
			} 
			else 
			{
				if (plusLoc == -1) plusLoc = eLoc;
				var places = newVal.substring(plusLoc + 1, newVal.length);
				justNumber = this.moveDecimalAsString(justNumber, false, parseInt(places));
			}
			newVal = justNumber;
		}
		return newVal;
	},
	
	moveDecimalRight: function(val, places)
	{
		var newVal = '';
		if (places == null) 
		{
			newVal = this.moveDecimal(val, false);
		} 
		else 
		{
			newVal = this.moveDecimal(val, false, places);
		}
		return newVal;
	},
	
	moveDecimalLeft: function(val, places)
	{
		var newVal = '';
		if (places == null) 
		{
			newVal = this.moveDecimal(val, true);
		} 
		else 
		{
			newVal = this.moveDecimal(val, true, places);
		}
		return newVal;
	},
	
	moveDecimalAsString: function(val, left, places)
	{
		var spaces = (arguments.length < 3) ? this.places : places;
		if (spaces <= 0) return val; 
		
		var newVal = val + '';
		var extraZ = this.getZeros(spaces);
		var re1 = new RegExp('([0-9.]+)');
		
		if (left) 
		{
			newVal = newVal.replace(re1, extraZ + '$1');
			var re2 = new RegExp('(-?)([0-9]*)([0-9]{' + spaces + '})(\\.?)');		
			newVal = newVal.replace(re2, '$1$2.$3');
		}
		else
		{
			var reArray = re1.exec(newVal); 
			if (reArray != null) 
			{
				newVal = newVal.substring(0,reArray.index) + reArray[1] + extraZ + newVal.substring(reArray.index + reArray[0].length); 
			}
			var re2 = new RegExp('(-?)([0-9]*)(\\.?)([0-9]{' + spaces + '})');
			newVal = newVal.replace(re2, '$1$2$4.');
		}
		newVal = newVal.replace(/\.$/, ''); 
		return newVal;
	},
	
	moveDecimal: function(val, left, places)
	{
		var newVal = '';
		if (places == null) 
		{
			newVal = this.moveDecimalAsString(val, left);
		} 
		else
		{
			newVal = this.moveDecimalAsString(val, left, places);
		}
		return parseFloat(newVal);
	},
	
	getRounded: function(val)
	{
		val = this.moveDecimalRight(val);

		if (this.truncate) 
		{
			val = val >= 0 ? Math.floor(val) : Math.ceil(val); 
		} 
		else
		{
			val = Math.round(val);
		}
		val = this.moveDecimalLeft(val);
		return val;
	},
	
	preserveZeros: function(val)
	{
		var i;
		val = this.expandExponential(val);
		if (this.places <= 0) return val; 
		
		var decimalPos = val.indexOf('.');
		
		if (decimalPos == -1) 
		{
			val += '.';
			for (i = 0; i < this.places; i++) 
			{
				val += '0';
			}
		}
		else
		{
			var actualDecimals = (val.length - 1) - decimalPos;
			var difference = this.places - actualDecimals;
			for (i = 0; i < difference; i++) 
			{
				val += '0';
			}
		}
		return val;
	},
	
	justNumber: function(val)
	{
		newVal = val + '';
		var isPercentage = false;
		if (newVal.indexOf('%') != -1) 
		{
			newVal = newVal.replace(/\%/g, '');
			isPercentage = true; 
		}
		
		var re = new RegExp('[^\\' + this.inputDecimalValue + '\\d\\-\\+\\(\\)eE]', 'g');	
		newVal = newVal.replace(re, '');
		var tempRe = new RegExp('[' + this.inputDecimalValue + ']', 'g');
		var treArray = tempRe.exec(newVal); 

		if (treArray != null) 
		{
			var tempRight = newVal.substring(treArray.index + treArray[0].length); 
			newVal = newVal.substring(0,treArray.index) + this.PERIOD + tempRight.replace(tempRe, ''); 
		}

		if (newVal.charAt(newVal.length - 1) == this.DASH ) 
		{
			newVal = newVal.substring(0, newVal.length - 1);
			newVal = '-' + newVal;
		}
		else if (newVal.charAt(0) == this.LEFT_PAREN && newVal.charAt(newVal.length - 1) == this.RIGHT_PAREN) 
		{
			newVal = newVal.substring(1, newVal.length - 1);
			newVal = '-' + newVal;
		}

		newVal = parseFloat(newVal);
		if (!isFinite(newVal)) 
		{
			newVal = 0;
		}
		if (isPercentage) 
		{
			newVal = this.moveDecimalLeft(newVal, 2);
		}
		return newVal;
	},
	
	abs: function()
	{
	    this.num = Math.abs(this.num);
	    return this;
	}
});

// Money
var Money = {};

Object.extend(Money, {

    parse: function(num, sep) 
    {
        return new Decimal(num, 2);
    },

    format: function(num)
    {
       return new Decimal(num, 2).toFormatted();
    }
});

// Guid
var Guid = function() 
{
	this.__value = Guid.newGuid();
};

Object.extend(Guid.prototype, 
{
    toFormatted: function(format)
    {
        switch(format)
        {
            case "N": // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                return this.__value.replace(/{|-|}/g, "");
            case "D": // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                return this.__value.replace(/{|}/g, "");
            case "B": // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} 
                return this.__value;
            case "P": // (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) 
                return this.__value.replace(/{/g, "(").replace(/}/g, ")");
        }
		return this.__value;
    }
});

Object.extend(Guid, {


    empty: function()
    {
        var guid = new Guid();
        var g = "{";
        for(var i = 0; i < 32; i++)
            g += "0" + (i == 8 || i == 12 || i == 16 || i == 20 ? "-" : "");
        guid.__value = g + "}";
        return guid;
    },
    
    newGuid: function()
    {
        var g = "{";
        for(var i = 0; i < 32; i++)
            g += Math.floor(Math.random() * 0xF).toString(0xF) + (i == 8 || i == 12 || i == 16 || i == 20 ? "-" : "");
        return g + "}";
    }
});


var Globals = new Data.Dictionary();

