/**
 * A participant in a subscriber chain that reads and updates state saved in a cookie.
 *
 * Requires:
 *	Properties.js
 *	Publisher.js
 */
function StateCookiePublisherAndSubscriber()
{
	var itsCookie;
	var itsParameterMappings = new Properties();
	var itsCurrentState;


	Publisher(this);


	function resetState()
	{
		itsCurrentState = null;
	}


	this.publisherChanged = function()
	{
		var theKeys;
		var i;
		var theArgumentIndex;
		var isChanged;
		var theProperties;

		isChanged = false;
		theKeys = itsParameterMappings.getKeys();
		for (i = 0; i < theKeys.length; i++)
		{
			theArgumentIndex = itsParameterMappings.getProperty(theKeys[i]);
			if (!itsCurrentState || !itsCurrentState.length || itsCurrentState[i] != arguments[theArgumentIndex])
			{
				isChanged = true;
				if (!itsCurrentState)
					itsCurrentState = new Array();
				itsCurrentState[i] = arguments[theArgumentIndex];
				if (!theProperties)
					theProperties = new Properties();
				theProperties.setProperty(theKeys[i],arguments[theArgumentIndex]);
			}
		}

		if (!isChanged)
			return;

		// Update the cookie.
		itsCookie.setValue(theProperties.asQueryString());

		// Notify the subscribers.
		this.notifySubscribers.apply(this,itsCurrentState);
	};


	this.readCookie = function()
	{
		var theCookieValue;
		var theState;
		var theKeys;
		var theParameters;
		var i;

		theCookieValue = itsCookie.getValue();
		if (!theCookieValue || theCookieValue == "")
		{
			if (arguments.length > 0)
			{
				itsCurrentState = Array.prototype.slice.apply(arguments,[0]);
				this.notifySubscribers.apply(this,itsCurrentState);
			}
		}
		else
		{
			theState = new Properties();
			theState.parseQueryString(theCookieValue);
			theParameters = new Array();
			theKeys = itsParameterMappings.getKeys();
			for (i = 0; i < theKeys.length; i++)
				theParameters[itsParameterMappings.getProperty(theKeys[i])] = theState.getProperty(theKeys[i]);
			this.publisherChanged.apply(this,theParameters);
		}
	};


	this.getCookie = function()
	{
		return (itsCookie);
	};


	this.setCookie = function(inCookie)
	{
		itsCookie = inCookie;
	};


	this.clearParameterMappings = function()
	{
		itsParameterMappings.clear();
		resetState();
	}


	this.addParameterMapping = function(inName,inIndex)
	{
		itsParameterMappings.setProperty(inName,inIndex);
		resetState();
	};
}
