/// <summary>
///		Constructor. Can take a serialized value, or initialize raw (acts as its own overload).
/// </summary>
function ReportContext( serialized )
{
	this._Mapping = {};
	this._Keys = [];
	if ( serialized == null ) return;
	
	var Pairs = serialized.split(":");
	for ( var i in Pairs )
	{
		var Pair = Pairs[i];
		var KeyVal = Pair.split("|");

		this._Mapping[KeyVal[0]]=KeyVal[1];
		this._Keys.push( KeyVal[0] );

	}
}

/// <summary>
///		Serializes the ReportContext to a string
/// </summary>
/// <remarks>
///		Note that (new ReportContext(x)).ToString() != x, because order of values is arbitrary. See Compare method for better comparisons.
/// </remarks>
function ReportContextToString()
{
	var Pairs = [];
	for ( var i in this._Keys )
	{
		var key = this._Keys[i];
		Pairs.push( [key,this._Mapping[key]].join("|") );
	}
	
	return Pairs.join(":");
}

/// <summary>
///		Gets the value for a given key. Null if this key isn't part of the ReportContext
/// </summary>
function ReportContextGet( key )
{
	return this._Mapping[key];
}

/// <summary>
///		Sets a key to a given value
/// </summary>
function ReportContextSet( key, val )
{
	if ( this.Get( key ) == null )
		this._Keys.push( key );
	this._Mapping[key] = val;
	return val;
}

/// <summary>
///		Compares to another ReportContext. Works similarly to the server-side Search function of ContextTrees in that
///		an integer "match strength" is returned, with -1 returned if the contexts conflict.
/// </summary>
function ReportContextCompare( rc )
{
	var m = 0;
	for ( var k in this._Keys )
	{
		var key = this._Keys[k];
		if ( rc.Get( key ) != null )
		{
			if ( rc.Get( key ) != this.Get( key ) )
				return -1;
			m++;
		}
	}
	
	return m;
}

ReportContext.prototype.ToString = ReportContextToString;
ReportContext.prototype.Get = ReportContextGet;
ReportContext.prototype.Set = ReportContextSet;
ReportContext.prototype.Compare = ReportContextCompare;