/**
 * Functies voor het omgaan met array-like objects.
 */

/**
 * Controleer of een variabele een array-like object is.
 * Een array-like object is een object wat in alle opzichten op
 * een array lijkt. De properties van het object zijn numerieke
 * strings, vanaf "0" oplopend, en er is een "length"-property
 * waarin het aantal items bijgehouden wordt. Bij het toevoegen
 * en verwijderen van items moet je zelf zorgen voor het
 * aanpassen van de nummering en het bijwerken van 'length'.
 *
 * In principe is een gewone array praktischer, maar er zijn
 * gevallen waarin die problemen geeft. Voor Toerkoop heel
 * concreet bij het kopieren van toerengine-instellingen vanuit het
 * history-iframe naar de hoofdpagina. In Firefox 3 bleken alle
 * arrays ineens te zijn geconverteerd naar array-like objects.
 * Daarom worden voor de instellingen per definitie array-like
 * objects gebruikt en geen gewone arrays.
 */
function isArraylikeObject(variable)
{
	if (!variable || typeof variable !== 'object')
		return false;

	if (typeof variable.length !== 'number')
		return false;

	var maxI = -1;
	var loopCount = 0;
	for (var i in variable)
	{
		if (i === 'length')
			continue;

		if (!i.match(/^[0-9]+$/))
		{
			// Als er een niet-numeriek item wordt gevonden, is het geen
			// array-like object.
			return false;
		}

		loopCount++;
		maxI = Math.max(parseInt(i, 10), maxI);
	}

	if (loopCount != variable.length || maxI != loopCount-1)
	{
		// Dan zijn alle items wel numeriek, maar met gaten in de nummering,
		// of het aantal items klopt niet met wat er in 'length' staat.
		return false;
	}

	return true;
}

var alo =
{
	/**
	 * Zoekt het eerste element met de waarde val en verwijdert dat element.
	 * Geeft de index van het verwijderde element terug, of false als de
	 * waarde val niet gevonden wordt.
	 */
	'removeValue': function(alobj, val)
	{
		if (!isArraylikeObject(alobj))
			return false;

		var index = false;
		for (var i = 0; i < alobj.length; i++)
			if (alobj[i] == val || index !== false)
			{
				if (index === false)
				{
					alobj.length--;
					index = i;
				}

				if (i < alobj.length)
					alobj[i] = alobj[i+1];
			}

		if (index !== false)
			delete alobj[alobj.length];

		return index;
	},

	/**
	 * Verwijdert het element met de index index, als die binnen de length
	 * van de array voorkomt. Geeft de waarde van het verwijderde element
	 * terug, of undefined als de index niet gevonden wordt.
	 */
	'removeIndex': function(alobj, index)
	{
		if (!isArraylikeObject(alobj))
			return false;

		index = parseInt(index);
		if (index < 0 || index >= alobj.length)
			return false;

		var val; // waarde is undefined

		for (var i = index; i < alobj.length; i++)
		{
			if (i == index)
			{
				alobj.length--;
				val = alobj[i];
			}

			if (i < alobj.length)
				alobj[i] = alobj[i+1];
		}

		delete alobj[alobj.length];

		return val;
	},

	'convertToArray': function(alobj)
	{
		if (!isArraylikeObject(alobj))
			return false;

		var out = [ ];
		for (var i = 0; i < alobj.length; i++)
			out.push(alobj[i]);

		return out;
	}
};
