<!--
    * 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="../dojo/dojo.js"></script>
<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;
	}
	
	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().addCallback(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("").addCallback(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>item</title><content type="text/xml">' +
                	'<Item xmlns="http://services/">' +
                	'<name xmlns="">' + catalogItems[i].name + '</name>' + '<price xmlns="">' + catalogItems[i].price + '</price>' +
                 	'</Item>' + '</content></entry>';
				shoppingCart.post(entry).addCallback(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("");
	}
	function deleteCart() {
		shoppingCart.del("");
		document.getElementById('shoppingCart').innerHTML = "";
		document.getElementById('total').innerHTML = "";	
	}	

	function init() {
		try	{
			catalog.get().addCallback(catalog_getResponse);
			shoppingCart.get("").addCallback(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/Cart/">(feed)</a>
	</form>    
  </div>
</body>
</html>
