<!--
    * 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>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
<title>Store</title>

<script type="text/javascript" src="/all-min.js"></script>

<script type="text/javascript">
var store = sca.component("Store");
var catalog = sca.defun(sca.reference(store, "catalog"), "items");
var shoppingCart = sca.reference(store, "shoppingCart");
var shoppingTotal = sca.defun(sca.reference(store, "shoppingTotal"), "total");

var catalogItems;

function catalog_itemsResponse(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(doc) {
    if (doc != null) {
        var feed = parseXML([doc]);
        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;

        shoppingTotal.total(shoppingTotal_totalResponse);
    }
}

function shoppingTotal_totalResponse(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 = '<?xml version="1.0" encoding="UTF-8"?>\n' +
            '<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><content type="application/xml">' +
            '<item>' +
            '<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.items(catalog_itemsResponse);
        shoppingCart.get("", shoppingCart_getResponse);
    } catch(e){
        alert(e);
    }
}
</script>
</head>

<body onload="init()">
<h1>Store</h1>
<br/>
<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>
