<!--
    * Licensed to the Apache Software Foundation (ASF) under one
    * or more contributor license agreements.  See the NOTICE file
    * distributed with this work for additional information
    * regarding copyright ownership.  The ASF licenses this file
    * to you under the Apache License, Version 2.0 (the
    * "License"); you may not use this file except in compliance
    * with the License.  You may obtain a copy of the License at
    * 
    *   http://www.apache.org/licenses/LICENSE-2.0
    * 
    * Unless required by applicable law or agreed to in writing,
    * software distributed under the License is distributed on an
    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    * KIND, either express or implied.  See the License for the
    * specific language governing permissions and limitations
    * under the License.    
-->
<html>
<head>
<title>Store</title>

<script type="text/javascript" src="store.js"></script>

<script language="JavaScript">

	//@Reference
	var catalog = new tuscany.sca.Reference("catalog");
	
	//@Reference
	var shoppingCart = new tuscany.sca.Reference("shoppingCart");

	//@Reference
	var shoppingTotal = new tuscany.sca.Reference("shoppingTotal");
	
	var catalogItems;

	function catalog_getResponse(items,exception) {
		if(exception){
			alert(exception.message);
			return;
		}
		var catalog = "";
		
		for (var i=0; i<items.length; i++) {
			var item = items[i].name + ' - ' + items[i].price;
			catalog += '<input name="items" type="checkbox" value="' + 
						item + '">' + item + ' <br>';
		}
		document.getElementById('catalog').innerHTML=catalog;
		catalogItems = items;

		// TEMP		
		shoppingTotal.gettotal(shoppingTotal_getTotalResponse);
	}
	
	function shoppingCart_getResponse(feed) {
		if (feed != null) {
			var entries = feed.getElementsByTagName("entry"); 
			var list = "";
			for (var i=0; i<entries.length; i++) {
				var content = entries[i].getElementsByTagName("content")[0];
				var name = content.getElementsByTagName("name")[0].firstChild.nodeValue;
				var price = content.getElementsByTagName("price")[0].firstChild.nodeValue;
				list += name + ' - ' + price + ' <br>';
			}
			document.getElementById("shoppingCart").innerHTML = list;

			if (entries.length != 0) {			
					try	{
						shoppingTotal.gettotal(shoppingTotal_getTotalResponse);
					}
					catch(e){
						alert(e);
					}
			}
		}
	}
	
	function shoppingTotal_getTotalResponse(total,exception) {
		if(exception) { 
			alert(exception.message); 
			return;
		}
		document.getElementById('total').innerHTML = total;
	}
	
	function shoppingCart_postResponse(entry) {
		shoppingCart.get("", shoppingCart_getResponse);
	}				

	function addToCart() {
		var items  = document.catalogForm.items;
		var j = 0;
		for (var i=0; i<items.length; i++)
			if (items[i].checked) {
				var entry = '<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><content type="application/xml">' +
                '<item>' +
                '<javaClass>' + catalogItems[i].javaClass + '</javaClass>' +
                '<name>' + catalogItems[i].name + '</name>' +
                '<currencyCode>' + catalogItems[i].currencyCode + '</currencyCode>' +
                '<currencySymbol>' + catalogItems[i].currencySymbol + '</currencySymbol>' +
                '<price>' + catalogItems[i].price + '</price>' +
                '</item>' +
                '</content></entry>';
				shoppingCart.post(entry, shoppingCart_postResponse);
				items[i].checked = false;
			}
	}
	function checkoutCart() {
		document.getElementById('store').innerHTML='<h2>' +
				'Thanks for Shopping With Us!</h2>'+
				'<h2>Your Order</h2>'+
				'<form name="orderForm">'+
					document.getElementById('shoppingCart').innerHTML+
					'<br>'+
					document.getElementById('total').innerHTML+
					'<br>'+
					'<br>'+
					'<input type="submit" value="Continue Shopping">'+ 
				'</form>';
		shoppingCart.del("", null);
	}
	function deleteCart() {
		shoppingCart.del("", null);
		document.getElementById('shoppingCart').innerHTML = "";
		document.getElementById('total').innerHTML = "";	
	}	

	function init() {
			
			try	{
				catalog.get(catalog_getResponse);
				shoppingCart.get("", shoppingCart_getResponse);
			}
			catch(e){
				alert(e);
			}
		}
	
</script>

</head>

<body onload="init()">
<h1>Store</h1>
  <div id="store">
   	<h2>Catalog</h2>
   	<form name="catalogForm">
		<div id="catalog" ></div>
		<br>
		<input type="button" onClick="addToCart()"  value="Add to Cart">
   	</form>
 
 	<br>
  
   	<h2>Your Shopping Cart</h2>
   	<form name="shoppingCartForm">
		<div id="shoppingCart"></div>
		<br>
		<div id="total"></div>
		<br>		
		<input type="button" onClick="checkoutCart()" value="Checkout"> 
		<input type="button" onClick="deleteCart()" value="Empty">     
	   	<a href="../shoppingCart/">(feed)</a>
	</form>    
  </div>
</body>
</html>
