
var imagePath184x184 = '/images/products/184x184/';
var imagePath225x225 = '/images/products/225x225/';
var imagePath400x400 = '/images/products/400x400/';


/**
 * Seeks the specified product.
 * @param productId the id of the product to find.
 * @returns the found product; or false if no matching product was found.
 */
function findProduct (productId)
{
	var product = null;

	for (var i=0; i<products.length; i++)
	{
		if (products[i].id == productId)
		{
			return products[i];
		}
	}
	
	alert (i18cannotfindproduct + productId);
}

/**
 * Sizes the overlay.
 * The dimension of the overlay need to be calculated other than by simply taking
 * the applicable document.body or window properties, because these methods fail for 
 * elements that are positioned as 'absolute'. 
 */
function sizeOverlay() {
	var mask = Ext.get('overlayinfo');
    mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
}

/**
 * Initializes the overlay.
 * Required for the search result dialog, which is not ajax driven.
 */
Event.observe(window, 'load', sizeOverlay);

/**
 * Shows the dialog that is specified by given the container.
 * @param dialogContainerId the dialog container id.
 * @return void;
 */
function showDialog (dialogContainerId)
{
	// Resize the overlay to the document dimensions.
	sizeOverlay ();

	// Show the overlay.
	$('overlayinfo').show();

	// Place the dialog in the viewport.
	var dialogElement = $(dialogContainerId);
	dialogElement.show ();
	
	var dialogHeight = dialogElement.getHeight();
	var position = document.viewport.getScrollOffsets();
	var top = (position.top + 80);
	var overlayHeight = Ext.lib.Dom.getViewHeight(true); 

	if (top + dialogHeight > overlayHeight) {
		top = Math.max(0, overlayHeight - dialogHeight)
	}
	dialogElement.setStyle ('top: ' + top + 'px;');
}

/**
 * Hides the dialog that is specified by the given container id.
 * @param dialogContainerId the dialog container id.
 * @return void;
 */
function hideDialog(dialogContainerId)
{
	$(dialogContainerId).hide();
	$('overlayinfo').hide();
}

/**
 * Creates the HTML for a packaging options select box.
 * @param elementId		the element id.
 * @param packagingOptions	packaging options array.
 * @return the generated html.
 */
function createPackagingOptionSelectHtml (elementId, packagingOptions)
{
	var packageTypes = [];
	var index = 0;
	packageTypes[index++] = '<select id="' + elementId + '">';

	for (var i=0; i<packagingOptions.length; i++)
	{
		var box = packagingOptions[i];
		if (box == undefined)
		{
			// This may happen on IE.
			// Box arrays are automatically appended with a ',' separator and IE
			// expects another element and counts one element more than
			// FireFox.  
			continue;
		}
		
		var packageType = box.packageType;
		if (packageType == '')
		{
			// Skip empty elements.
			continue;
		}
		
		packageTypes[index++] = '<option value="';
		packageTypes[index++] = packageType;
		packageTypes[index++] = '">';
		packageTypes[index++] = packageType; 
		packageTypes[index++] = '</option>';
	}

	packageTypes[index++] = '</select>';
	return packageTypes.join ('');
}

function getVerpakteCymbidiumHtml (product)
{
	var html = [];
	var index = 0;

	html[index++] = '<h1>'+i18ProductDetailsTitle+'</h1>';
	html[index++] = '<table><col width="160px" /><col />';
	// Article number
	html[index++] = '<tr><td class="element">'+i18ArticleNumber+'</td><td>';
	html[index++] = product.articleCode;
	html[index++] = '</td></tr>';
	// Product name
	html[index++] = '<tr><td class="element">'+i18ProductName+'</td><td>';
	html[index++] = product.name;
	html[index++] = '</td></tr>';
	// Units per package
	html[index++] = '<tr><td class="element">'+i18NumberOfFlowers+'</td><td>';
	html[index++] = product.flowers;
	html[index++] = '</td></tr>';
	// Eurodoos dimensions
	if (product.hasEuroBox)
	{
		html[index++] = '<tr><td class="element">'+i18Dimensions+'</td><td>';
		html[index++] = product.euroBoxDimensions;
		html[index++] = ' cm';
		html[index++] = '</td></tr>';
	}
	
	// Display all packaging options
	for (var i=0; i<product.packagingOptions.length; i++)
	{
		html[index++] = '<tr><td class="element">';
		html[index++] = product.packagingOptions[i].packageType;
		html[index++] = '</td><td>';
		html[index++] = product.packagingOptions[i].count;
		html[index++] = ' ' + i18Pieces;
		if (product.packagingOptions[i].weight > 0)
		{
			html[index++] = ' (';
			html[index++] = product.packagingOptions[i].weight;
			html[index++] = ' kg)';
		}
		html[index++] = '</td></tr>';
	}

	// Mantis #1046
	var showLoadCarriers = product.hasEuroBox;

	if (showLoadCarriers)
	{
		for (var i=0; i<product.packagesPerLayer.length; i++)
		{
			if (product.packagesPerLayer[i].loadCarrierId == '999')
			{
				showLoadCarriers = false;
				break;
			}
		}
	}
	
	if (showLoadCarriers)
	{		
		// Packages per layer (Eurodoos)
		html[index++] = '<tr><td><br/><br/><strong>'+i18PackagesPerLayer+'</strong></td><td></td></tr>';
		// Load carriers (Eurodoos)
		for (var i=0; i<product.packagesPerLayer.length; i++)
		{
			html[index++] = '<tr><td class="element">';
			html[index++] = product.packagesPerLayer[i].loadCarrierName;
			html[index++] = '</td><td>'; 
			html[index++] = product.packagesPerLayer[i].packagesPerLayer;
			html[index++] = '</td></tr>';
		}
	}

	html[index++] = '</table>';

	return html.join ('');
}

function getNonVerpakteCymbidiumHtml (productGroup, product)
{
	var html = [];
	var index = 0;

	html[index++] = '<h1>'+i18ProductDetailsTitle+'</h1>';
	html[index++] = '<table><col width="140px" /><col />';

	// Product name
	html[index++] = '<tr><td class="element">'+i18Name+'</td><td>';
	html[index++] = product.name;
	html[index++] = '</td></tr>';

	// Article number
	if (productGroup == 1 || productGroup == 4)
	{
		html[index++] = '<tr><td class="element">'+i18VbnCode+'</td><td>';
	} else
	{	
		html[index++] = '<tr><td class="element">'+i18ArticleNumber+'</td><td>';
	}
	html[index++] = product.articleCode;
	html[index++] = '</td></tr>';
	
	// Valid from to
	if (productGroup == 1 || productGroup == 4) {
		html[index++] = '<tr><td class="element">'+i18AvailableFrom+'</td><td>';
		html[index++] = product.validFromMonth;
		html[index++] = '</td></tr>';		
	} else if (productGroup == 2 || productGroup == 3) {
		html[index++] = '<tr><td class="element">'+i18AvailableFrom+'</td><td>';
		html[index++] = product.validFrom;
		html[index++] = '</td></tr>';
	}

	
	// Cymbidium takken
	if (productGroup == 1) {	
		// rocy.site.catalog.productdetails.length
		html[index++] = '<tr><td class="element">'+i18Length+'</td><td>';
		html[index++] = product.length;
		html[index++] = '</td></tr>';

		// Flowers min/max
		html[index++] = '<tr><td class="element">'+i18NumberOfFlowersPerTak+'</td><td>';
		html[index++] = product.minFlowers + "/" + product.maxFlowers;
		html[index++] = '</td></tr>';
	} else if (productGroup == 2 || productGroup == 3) {
		// Phalaenopsis, Phalaenopsis XL
		
		// Flowers
		html[index++] = '<tr><td class="element">'+i18NumberOfFlowers+'</td><td>';
		html[index++] = product.flowers1;
		html[index++] = '</td></tr>';

		// Flower pot
		html[index++] = '<tr><td class="element">'+i18FlowerPot+'</td><td>';
		html[index++] = product.flowerPot;
		html[index++] = '</td></tr>';

		// Stadium
		html[index++] = '<tr><td class="element">'+i18Stadium+'</td><td>';
		html[index++] = product.stadium;
		html[index++] = '</td></tr>';						
	}
	
	if (productGroup == 2 || productGroup == 3) {
	// Packaging
	html[index++] = '<tr><td class="element">'+i18FloraPackage+'</td><td>';
	html[index++] = product.floraPackageDescription;
	html[index++] = '</td></tr>';						
	}
	
	if (productGroup == 4) {
		html[index++] = '<tr><td class="element">'+i18PotCapacity+'</td><td>';
		html[index++] = product.potCapacity;
		html[index++] = '</td></tr>';	
		
		html[index++] = '<tr><td class="element">'+i18FloweringTime+'</td><td>';
		html[index++] = product.validFromMonth;
		html[index++] = '</td></tr>';
		
		html[index++] = '<tr><td class="element">'+i18PotSoil+'</td><td>';
		html[index++] = product.potSoil;
		html[index++] = '</td></tr>';
		
		html[index++] = '<tr><td class="element">'+i18LengthTak+'</td><td>';
		html[index++] = product.length;
		html[index++] = '</td></tr>';
	}
	else {
		
		if (productGroup == 1) {
			html[index++] = '<tr><td class="element">'+i18UnitsPerBox+'</td><td>';
			html[index++] = product.unitsPerPackage;
			html[index++] = '</td></tr>';
			
			// Packaging
			html[index++] = '<tr><td class="element">'+i18FloraPackagecode+'</td><td>';
			html[index++] = product.floraPackageDescription;
			html[index++] = '</td></tr>';			
			
		} else {
			// Units per package
			html[index++] = '<tr><td class="element">'+i18UnitsPerPackage+'</td><td>';
			html[index++] = product.unitsPerPackage;
			html[index++] = '</td></tr>';
		
		
		// Mantis #1046
			if (product.loadCarrierId != '999')
			{
				// Load carrier
				html[index++] = '<tr><td class="element">'+i18LoadCarrier+'</td><td>';
				html[index++] = product.loadCarrierDescription;
				html[index++] = '</td></tr>';		
						
				// Packages per layer
				html[index++] = '<tr><td class="element">'+i18PackagesPerLayer+'</td><td>';
				html[index++] = product.packagesPerLayer1;
				html[index++] = '</td></tr>';
			
				// Layers per carrier
				html[index++] = '<tr><td class="element">'+i18LayersPerCarrier+'</td><td>';
				html[index++] = product.layersPerCarrier
				html[index++] = '</td></tr>';
			}
		}
	}
	
	if (productGroup == 1 || productGroup == 4) {
		html[index++] = '<tr><td class="element">'+i18Remarks+'</td><td>';
		html[index++] = product.remarks
		html[index++] = '</td></tr>';
	}
	
	html[index++] = '</table>';

	return html.join ('');
}

function getProductInfoHtml (product, productGroup)
{
	if (productGroup == 0)
	{
		return getVerpakteCymbidiumHtml (product);
	}

	return getNonVerpakteCymbidiumHtml (productGroup, product);
}

function getInfoPopupEmailHtml (product, productGroupId)
{
	var productId = product.id;
	
	var html = [];
	var index = 0;

	html[index++]='<div id="productEmail">';

	html[index++]='<strong>Stuur product door naar e-mailadres:</strong><br/>';
	html[index++]='<input id="email" type="text" name="email" style="width:250px; border: 1px solid #cccccc"/><a href="#" onclick="javascript: Aphrodite.sendLinkToEmail ('+productId+', '+productGroupId+'); return false;">&nbsp;<img src="/aphrodite/images/btn_send.gif" style="border:0px; vertical-align:bottom;"/></a>';
	html[index++]='<br><br>';
	if (product.soldOut)
	{
		html[index++]='<strong>Dit artikel is uitverkocht, indien u infomatie wenst dan kunt u dat <a href="/site/nl/ao/algemeen/contact">hier</a> aanvragen.</strong><br/><br/>';
	}
	html[index++]='</div>';
	return html.join ('');
}

/**
 * Opens the product information window.
 * @param productId		the product id.
 * @param imageId		the image id.
 * @return void
 */
function openInfoWindow (productId, productGroup, imageId)
{
	var product = findProduct (productId);

	var html = [];
	var index = 0;

	html[index++] = getProductInfoHtml (product, productGroup);
	
	html[index++] = getInfoPopupEmailHtml (product, productGroup);
	
	// Close link
	html[index++] = '<div class="infopopupleftfooter">';
	// Order product link
	var disabled = true;
	if (!disabled && !product.soldOut)
	{
		html[index++] = '<a href="#" onclick="hideDialog(\'overlayinfocontainer\'); openOrderWindow (';
		html[index++] =	product.id;
		html[index++] = ','; 
		html[index++] = imageId;
		html[index++] = '); return false;" style="float:left"><img src="/aphrodite/images/btn_order.gif"/ style="border:0px; vertical-align:bottom;">&nbsp;'+i18OrderProduct+'</a>';
	}

	$('infopopupleft').innerHTML = html.join ('');
	// Create the download picture links.
	var path72dpi = '/download.web?id=' + productId + '&dpi=72';
	var path300dpi = '/download.web?id=' + productId + '&dpi=300';
	var html = "";

	// The 72dpi images has two purposes: it can be downloaded; and we
	// use it as product image in the product information screen.
	if (product.has72dpiImage)
	{
		// Create the 72dpi download link
		html += '<a href="' + path72dpi + '" style="float:left;"><img src="/aphrodite/images/btn_dl.gif" alt="" style="border:0px;"/>&nbsp;Download web (72 dpi)</a>';

		// Load the image
		$('infopopupimg').innerHTML = '<img src="' + imagePath400x400 + imageId + '.jpg" />';
	} else
	{
		$('infopopupimg').innerHTML = '';
	}
	if (product.has300dpiImage)
	{
		html += '<a href="' + path300dpi + '" style="float:right;"><img src="/aphrodite/images/btn_dl.gif" alt="" style="border:0px"/>&nbsp;Download print (300 dpi)</a>';
	}
	
	$('infopopuprightfooter').innerHTML = html;

	// Enable or disable, as applicable, the sold out banner
	var soldoutinfo = $('soldoutinfo');
	var soldoutinfoImage = $('soldoutinfoImage');
	if (product.soldOut)
	{
		soldoutinfo.addClassName ('soldoutinfo');
		soldoutinfo.setStyle ('display: block;');
		soldoutinfoImage.setStyle ('display: block;');
	} else
	{
		soldoutinfo.removeClassName ('soldoutinfo');
		soldoutinfo.setStyle ('display: none;');
		soldoutinfoImage.setStyle ('display: none;');
	}

	
	showDialog ('overlayinfocontainer');
	AphroditeSIFR.init ();
} 

/**
 * Opens the product information window.
 * @param productId		the product id.
 * @param imageId		the image id.
 * @return void
 */
function openInfoWindow2 (productId, productGroup, imageId, imageId2)
{
	var product = findProduct (productId);

	var html = [];
	var index = 0;

	html[index++] = getProductInfoHtml (product, productGroup);
	html[index++] = getInfoPopupEmailHtml (product, productGroup);

	// Close link
	html[index++] = '<div class="infopopup2leftfooter">';
	// Order product link
	var disabled = true;
	if (!disabled && !product.soldOut)		
	{
		html[index++] = '<a href="#" onclick="hideDialog(\'overlayinfocontainer2\'); openOrderWindow (';
		html[index++] =	product.id;
		html[index++] = ','; 
		html[index++] = imageId;
		html[index++] = '); return false;" style="float:left"><img src="/aphrodite/images/btn_order.gif"/ style="border:0px; vertical-align:bottom;">&nbsp;'+i18OrderProduct+'</a>';
	}

	$('infopopup2left').innerHTML = html.join ('');
	// Create the download picture links.
	var path72dpi = '/download.web?id=' + productId + '&dpi=72';
	var path300dpi = '/download.web?id=' + productId + '&dpi=300';
	var html = "";

	// The 72dpi images has two purposes: it can be downloaded; and we
	// use it as product image in the product information screen.
	if (product.has72dpiImage)
	{
		// Create the 72dpi download link
		html += '<a href="' + path72dpi + '" style="float:left;"><img src="/aphrodite/images/btn_dl.gif" alt="" style="border:0px; vertical-align:bottom;"/>&nbsp;Download web (72 dpi)</a>';

		// Load the image
		$('infopopup2imgleft').innerHTML = '<img src="' + imagePath225x225 + imageId + '.jpg" />';
		$('infopopup2imgright').innerHTML = '<img src="' + imagePath225x225 + imageId2 + '.jpg" />';
	} else
	{
		$('infopopup2imgleft').innerHTML = '';
		$('infopopup2imgright').innerHTML = '';
	}
	if (product.has300dpiImage)
	{
		html += '<a href="' + path300dpi + '" style="float:right;"><img src="/aphrodite/images/btn_dl.gif" alt="" style="border:0px; vertical-align: bottom;"/>&nbsp;Download print (300 dpi)</a>';
	}
		
	$('infopopup2rightfooter').innerHTML = html;

	// Enable or disable, as applicable, the sold out banner
	var soldoutinfo = $('soldoutinfo2');
	//var soldoutinfo2right = $('soldoutinfo2right');

	var soldoutinfoImage = $('soldoutinfo2Image');
	if (product.soldOut)
	{
		soldoutinfo.addClassName ('soldoutinfo2');
		soldoutinfoImage.setStyle ('display: block;');
		//soldoutinfo2right.addClassName ('soldoutinfo2');
	} else
	{
		soldoutinfo.removeClassName ('soldoutinfo2');
		soldoutinfoImage.setStyle ('display: none;');
		//soldoutinfo2right.removeClassName ('soldoutinfo2');
	}
	
	showDialog ('overlayinfocontainer2');
	AphroditeSIFR.init ();
}

function openInfoWindowAdapter (productId, productGroup, image1Id, image2Id)
{
	//image2Id = 0;
	if (image1Id != 0 && image2Id != 0)
	{
		openInfoWindow2 (productId, productGroup, image1Id, image2Id);
	} else
	{
		openInfoWindow (productId, productGroup, image1Id);
	}
}


/**
 * Opens the order product window for the specified product id.
 * The order window enables the user to add the selected product to his or her basket.
 * @param productId		the product id.
 * @param imageId		the image id.
 * @return void
 */
function openOrderWindow (productId, imageId)
{			
	var product = findProduct (productId);

	$('order_productId').value = productId;
	$('order_productName').innerHTML = product.name;
	$('order_articleCode').innerHTML = product.articleCode;
	// Load the image
	$('orderpopupright').innerHTML = (product.has72dpiImage) ? '<img src="' + imagePath225x225 + imageId + '.jpg" />' : '';			
	$('order_boxes').value = 1;		
	
	var packageTypes = [];
	var index = 0;
	packageTypes[index++] = '<select id="order_packageTypeValue">';
	
	for (var i=0; i<product.packagingOptions.length; i++)
	{
		var box = product.packagingOptions[i];
		if (box == undefined)
		{
			// This may happen on IE.
			// Box arrays are lazily appended with a ',' separator and IE
			// expects another element and counts one element more than
			// FireFox.  
			continue;
		}
		
		var packageType = box.packageType;
		if (packageType == '')
		{
			// Skip empty elements.
			continue;
		}
		
		packageTypes[index++] = '<option value="';
		packageTypes[index++] = packageType;
		packageTypes[index++] = '">';
		packageTypes[index++] = packageType; 
		packageTypes[index++] = '</option>';
	}

	packageTypes[index++] = '</select>';
	$('order_packageType').innerHTML = packageTypes.join ('');

	$('orderpopupAdd').show ();
	$('orderpopupEdit').hide ();
	
	showDialog ('overlayordercontainer');
	AphroditeSIFR.init ();
}

/**
 * This function is derived from the openOrderWindow implementation.
 * TODO: Consider an alternative implementation.
 * @param basketItemId	the basked item identifier.
 * @param productId		the product identifier.
 * @param name			the product name.
 * @param articleCode	the article code.
 * @param boxTypes		the packaging options.
 * @param type			the selected packaging option.
 * @param boxCount		the ordered boxes
 * @param has225x225image	true if the 225x225 image is available; otherwise false.
 * @return void
 */ 
function showEditBasketItem (basketItemId, productId, name, articleCode, boxTypes, type, boxCount, has225x225image, imageId)
{
	$('order_editBasketItemId').value = basketItemId;
	$('order_productName').innerHTML = name;
	$('order_articleCode').innerHTML = articleCode;

	$('orderpopupright').innerHTML = has225x225image ? '<img src="' + imagePath225x225 + imageId + '.jpg" />' : '';
	$('order_boxes').value = (!boxCount) ? 1 : boxCount;
		
	var packageTypes = [];
	var index = 0;
	var selectedIndex = 0;
	packageTypes[index++] = '<select id="order_packageTypeValue">';
	for (var i=0; i<boxTypes.length; i++)
	{
		var packageType = boxTypes[i];
		if (packageType == undefined || packageType == '')
		{
			// Skip empty elements.
			continue;
		}
		
		packageTypes[index++] = '<option value="';
		packageTypes[index++] = packageType;

		if (packageType == type)
		{
			selectedIndex = i;
		}
		
		packageTypes[index++] = '">';
		packageTypes[index++] = packageType; 
		packageTypes[index++] = '</option>';
	}

	packageTypes[index++] = '</select>';
	$('order_packageType').innerHTML = packageTypes.join ('');
	$('order_packageType').selectedIndex = selectedIndex;

	$('orderpopupAdd').hide ();
	$('orderpopupEdit').show ();
	
	//showDialog ('overlayeditordercontainer');
	showDialog ('overlayordercontainer');
	AphroditeSIFR.init ();
}

function showFastBasket ()
{
	$('order_fastArticleCode').value = '';
	fastOrderEraseOrderDetails ();

	// TODO: Remove observer when the dialog closes
	Event.observe ('order_fastArticleCode', 'keypress', function (event) 
	{
		var keyCode = event.keyCode || event.which;
		if (keyCode == Event.KEY_RETURN)
		{
			fastOrderConfirmArticleCode ();
			return false;
		}
	});

	$('fastorderpopupalert').hide ();
	$('fastorderpopupleft').show ();
	$('fastorderpopupright').show ();

	showDialog ('overlayfastordercontainer');
	
}

/**
 * Closes the fast basket
 */
function hideFastBasket ()
{
	// TODO: Refactor
	new Ajax.Updater('basketDisplay', '/order.web?action=getBasketContentOrderForm&theme='+theme);
	hideDialog ('overlayfastordercontainer');
}

/**
 * Validates the basket.
 * @param boxes			ordered boxes.
 * @param packageType	ordered box type.
 * @return true if successfully validaded; otherwise false.
 */
function validateBasketItem (boxes, packageType)
{
	if (boxes < 1 || boxes > 100000)
	{
		alert (i18BoxesError);
		return false;
	}

	if (packageType == false)
	{
		alert (i18PackagingOptionError);
		return false;
	}
	
	return true;
}

/**
 * Adds the specified product to the shopping basket.
 * @param productId the product id.
 * @param packageType the selected packaging option.
 * @param boxes the number of boxes.
 * @param callback an optional callback, which can be used for various objectives.
 * @return void
 */
function addToBasket (productId, packageType, boxes, callback)
{
	if (!validateBasketItem (boxes, packageType))
	{
		return;
	}
	
	new Ajax.Request 
	(
		'/order.web',
		{
			method: 'post',
			parameters: {action: 'addToBasket', id: productId, type: packageType, number: boxes},
			onComplete: function (transport)
			{
				if (transport.status == 200 || transport.status == 404)
				{
					// TODO: consider refactoring
					new Ajax.Updater("basket", "/order.web?action=getBasket&theme="+theme);
				} else
				{
					alert (i18HttpError + transport.status);
				}

				if (callback != undefined)
				{
					callback (transport.status);
				}
			} // onComplete
		}
	);
}

/**
 *
 */
function editBasketItem ()
{
	var basketItemId = $('order_editBasketItemId').value;
	var boxes = $('order_boxes').value;		
	var packageType = $('order_packageTypeValue').value;
	
	
	if (!validateBasketItem (boxes, packageType))
	{
		return;
	}
	 
	new Ajax.Request 
	(
		'/order.web',
		{
			method: 'post',
			parameters: {action: 'editBasketItem', id: basketItemId, packageType: packageType, boxes: boxes},
			onComplete: function (transport)
			{
				if (transport.status == 200 || transport.status == 404)
				{
					hideDialog('overlayordercontainer');
											
					// TODO: consider refactoring
					// update order list in orderForm.jsp
					new Ajax.Updater('basketDisplay', '/order.web?action=getBasketContentOrderForm&theme='+theme);
					// update the basket info 
					new Ajax.Updater('basket', '/order.web?action=getBasket&theme='+theme);
				} else
				{
					alert (i18HttpError + transport.status);
				}
			}
		}
	);
}

/**
 * Removes the specified basket item from the basket.
 * @param basketItemId the basket item identifier.
 * @return void
 */
function removeFromBasket (basketItemId)
{
	var remove = confirm ("Weet u zeker dat u deze bestelling wilt verwijderen?");
	if (remove)
	{
		// Remove product.
		new Ajax.Request 
		(
			'/order.web',
			{
				method: 'post',
				parameters: {action: 'removeFromBasket', id: basketItemId},
				onComplete: function (transport)
				{
					if (transport.status == 200 || transport.status == 404)
					{
						toggleBasket ();
						// TODO: consider refactoring
						new Ajax.Updater('basket', '/order.web?action=getBasket&theme='+theme);							
					} else
					{
						alert (i18HttpError + transport.status);
					}
				}
			}
		);
	}
}

/**
 * Shows or hides, as applicable, the basket.
 * @return void
 */
function toggleBasket ()
{
	$('basketopen').toggle();
	$('basketopen_top').toggle();
}

function fastOrderConfirmArticleCode ()
{
	var selectGrowerElement = $('order_fastSelectGrower');
	var articleCodeElement = $('order_fastArticleCode');

	var articleCode = articleCodeElement.value.trim ();
	if (articleCode == '')
	{
		alert (i18ArticleCodeError);
		return;
	}

	new Ajax.Request 
	(
		'/catalog.web',
		{
			method: 'post',
			parameters: {action: 'getproductinformation', grower: selectGrowerElement.value, articleCode: articleCode},
			onComplete: function (transport)
			{
				if (transport.status == 200)
				{
					// Parse JSON reply
					var json = transport.responseText.evalJSON();

					if (json.result == -1)
					{
						// Error
						fastOrderEraseOrderDetails ();
						alert (json.message);
						return;
					}

					// Create UI elements.
					$('order_fastBasketProductId').value = json.product.id;
					$('order_fastProductName').innerHTML = json.product.name;
					$('order_fastPackageType').innerHTML = createPackagingOptionSelectHtml ('fastorderPackagingOption', json.product.packagingOptions);
					$('order_fastBoxesTD').innerHTML = '<input id="order_fastBoxes" type="text" class="order" style="width: 40px;" maxlength="5" />';
					$('fastorderpopupright').innerHTML = '<img src="' + imagePath225x225 + json.product.imageId + '.jpg" />';
					$('fastorder_add').show ();
				} else
				{
					alert ("Error: transport.status=" + transport.status);
				}
			}
		}
	);
}

/**
 * Erases the order details.
 */
function fastOrderEraseOrderDetails ()
{
	$('order_fastProductName').innerHTML = '';
	$('order_fastPackageType').innerHTML = '';
	$('order_fastBoxesTD').innerHTML = '';
	$('fastorderpopupright').innerHTML = '';
	$('fastorder_add').hide ();
}

/**
 * Adds the order to the basket.
 */
function fastBasketItem ()
{
	addToBasket ($('order_fastBasketProductId').value, $('fastorderPackagingOption').value, $('order_fastBoxes').value, fastItemAddedCallback);
}

/**
 * Continues the application flow when the preceding Ajax call is finished.
 */
function fastItemAddedCallback ()
{
	var articleCode = $('order_fastArticleCode').value;
	
	$('fastarticle1').innerHTML = articleCode;
	$('fastarticle2').innerHTML = articleCode;


	$('fastorderpopupleft').hide ();
	$('fastorderpopupright').hide ();
	$('fastorderpopupalert').show ();
}

/**
 * Prepares the next order entry.
 * The user may choose to enter a compelely new order or an order that
 * is based on an the previous article.
 * @param sameArticle a boolean that indicates if the same product will be ordered again (true); or a new product will be ordered (false).
 */
function fastItemNextOrder (sameArticle)
{
	if (!sameArticle)
	{
		$('order_fastArticleCode').value = '';
		$('order_fastProductName').innerHTML = '';
		$('order_fastPackageType').innerHTML = '';
		$('order_fastBoxesTD').innerHTML = '';
		$('fastorderpopupright').innerHTML = '';
	} else
	{
		$('order_fastBoxes').value = '';
		$('order_fastPackageType').focus ();
	}
	
	$('fastorderpopupalert').hide ();
	$('fastorderpopupleft').show ();
	$('fastorderpopupright').show ();
	
	$('order_fastArticleCode').focus ();
}

var postingOrder = false;
function postOrder ()
{
	if (postingOrder)
	{
		// prevent double clicks.
		return;
	}
	postingOrder = true;
	alert("Showing");
	showDialog ('overlayorderprocessingcontainer');
	
	// post the order form
	$('orderForm').request (
	{
		onComplete: function (transport)
		{
			var jsonResult = transport.responseText.evalJSON();
			
			hideDialog ('overlayorderprocessingcontainer');
			
			if (jsonResult.result == -1)
			{
				showDialog ('overlayordercompletedcontainer');

				var message = "";
				for (var i=0; i<jsonResult.errors.length; i++)
				{
					message += '<li>' + jsonResult.errors[i] + '</li>'; 
				}

				$('orderConfirmationStatusDialog').innerHTML = '<ul>' + message + '</ul>';		
			} else
			{
				// Redirect to the home page.
				window.location = '/site/nl/ao/';
			}

		}
	});
}

function chooseCatalogFastOrder (catalogUrl)
{
	showDialog ('overlaychooseordercontainer');
}

var Rocy = new function ()
{
	return {
	};
};

var Aphrodite = new function ()
{
	return {
		/**
		 * Aligns the designated elements to the bottom of the screen.
		 * @param elementIdArray an array with HTML element ids.
		 * @return void
		 */
		alignElementsToBottom: function (elementIdArray)
		{
			var mainElement = $('main');
			var mainRectangle = CoolJS.getRectangle (mainElement);

			for (var i = elementIdArray.length-1; i>=0; i--)
			{
				var elementId = elementIdArray[i];
				var element = $(elementId);

				var elementHeight = element.getHeight ();
				element.setStyle ('top: ' + (mainRectangle.height-elementHeight) + 'px;');
			}
		},

		/**
		 * Sends an e-mail, which contains the current URL, to the designated e-mail address.
		 * @param productId		the product id.
		 * @param productGroupIndex		the product group id.
		 * @return void
		 */
		sendLinkToEmail: function (productId, productGroupIndex)
		{
			var email = $('email').value;

			if (!CoolJS.validateEmail (email))
			{
				alert ("Ongeldig e-mail adres");
				return;
			}

			var url = window.location.href;
			url = url.replace (/open/, 'ignore'); 
			
			new Ajax.Request 
			(
				'/catalog.web',
				{
					method: 'post',
					parameters: {action: 'sendemail', 'productGroupIndex': productGroupIndex, 'email': email, 'url': url + "&open=" + productId + "&productGroupIndex=" + productGroupIndex},
					onComplete: function (transport)
					{
						if (transport.status == 200)
						{
							alert ("Email verstuurd naar " + email);
						} else
						{
							alert ("Email is niet verstuurd naar " + email);
						}
						
						$('email').value = '';
					}
				}
			);
			
			
		},
		
		/**
		 * Callback function for window resize events.
		 * @param void
		 * @return void
		 */
		resizeWindow: function ()
		{
		},

		/**
		 * Opens the product information page when the dom is loaded.
		 * Mantis #1067
		 * @return void.
		 */
		autoOpenWindow: function ()
		{
			var productId = CoolJS.getUrlParameter ('open');
			var productGroupIndex = CoolJS.getUrlParameter ('productGroupIndex');
			
			if (productId == null || productGroupIndex == null)
			{
				// No product info window.
				return;
			}

			var product = findProduct (productId);
			if (product == null)
			{
				return;
			}

			openInfoWindowAdapter (productId, productGroupIndex, product.publishedImage1Id, product.publishedImage2Id);
		}, 
		
		/**
		 * Callback function that is called when the DOM is ready.
		 * @param void
		 * @return void
		 */ 
		domLoaded: function ()
		{
			Aphrodite.autoOpenWindow ();
		}
	};
};

/**
 * Resizes the overlay.
 */
window.onresize = Aphrodite.resizeWindow;

/**
 * Initializes the overlay.
 * Required for the search result dialog, which is not ajax driven.
 */
document.observe("dom:loaded", Aphrodite.domLoaded); 


