/**
 * Copyright (c) 2004 Red Hat, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Component of: Red Hat Application Server
 * 
 * Initial Developers: Aizaz Ahmed
 *                     Vivek Lakshmanan
 *                     Andrew Overholt
 *                     Matthew Wringe
 *
 */
/*
 * ShoppingCartBean.java
 * 
 * Created on Aug 16, 2004
 *
 */
package olstore.session;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.math.BigDecimal;

import javax.ejb.SessionBean;

import olstore.dto.ShoppingCartItem;
import olstore.framework.EJBHomeFactory;

import olstore.entity.ItemLocal;
import olstore.entity.ItemLocalHome;
import olstore.entity.OrderLocalHome;
import olstore.entity.UserLocal;

/* The costs stored in the session bean would be unformatted float values,
 * @author mwringe
 *
 *  
 *
 */
/* it is the presentation layer's responsibility to enforce the formatting
 * @author mwringe
 *
 *  
 *
 */
/* the display of the costs.
 */

/**
 * @ejb.bean name="ShoppingCart"
 *	type="Stateful" 
 *  transaction-type="Container"
 *  view-type="local"
 *  local-jndi-name="ShoppingCartLocal_L"
 * 
 * @ejb.ejb-ref
 *  ejb-name="User"
 *  view-type="local"
 *  ref-name="ejb/UserLocal"
 * 
 * @ejb.ejb-ref
 *  ejb-name="Item"
 *  view-type="local"
 *  ref-name="ejb/ItemLocal"
 * 
 * @ejb.ejb-ref
 *  ejb-name="Order"
 *  view-type="local"
 *  ref-name="ejb/OrderLocal"
 * 
 * @ejb.transaction
 *  type="Required"
 *  
 *--
 * This is needed for JOnAS.
 * If you are not using JOnAS you can safely remove the tags below.
 * @jonas.bean ejb-name="ShoppingCart"
 * jndi-name="ShoppingCartLocal"
 * 
 *--
 **/

public abstract class ShoppingCartBean implements SessionBean {
    private UserLocal customer;
    private HashMap cart;
    private javax.ejb.SessionContext ejbContext;
    private javax.naming.Context initialContext;
    
    
    /**
     *
     * @ejb.create-method
     *
     */
    
    public void ejbCreate(olstore.entity.UserLocal user){
        customer = user;
        cart = new HashMap();
    }
    
    /**
     * 
     * @return User
     * 
     * @ejb.interface-method
     * 
     */
    
    public olstore.entity.UserLocal getUser(){
        return customer;
    }
    
    /**
     * 
     * Add items to shopping cart
     * 
     * @param itemPK
     * @param quantity
     * 
     * 
     */
     private void addItemToCart(Integer itemPK, Integer quantity){
        ItemLocal item = null;
        Integer qty;
        
        if(quantity.intValue() <= 0){
            
            throw new NumberFormatException("Quantity must be greater than 0:");
        }
        try{
            EJBHomeFactory factory = EJBHomeFactory.getInstance();
            ItemLocalHome home = (ItemLocalHome) factory.getLocalHome(EJBHomeFactory.ITEM);
            item = home.findByPrimaryKey(itemPK);
            if((qty = (Integer)cart.get(item))!=null){
                cart.remove(item);
            }
            cart.put(item, quantity);
            
        }catch(Exception e){
            throw new javax.ejb.EJBException("Could not add item "
                    + item , e);
        }
    }
    
    private BigDecimal recalculateTotal(){
        Iterator it = cart.keySet().iterator();
        BigDecimal totalCost = new BigDecimal(0.00f);
        
        while(it.hasNext())
            totalCost = totalCost.add(getCostForItem(((ItemLocal) it.next()).getItemId()));
        return totalCost;
    }
    
    /**
     * 
     * @param itemPK
     * @return quantity of those items in the cart
     * 
     * @ejb.interface-method
     * 
     */
    
    public Integer getQuantity(Integer itemPK){
        ItemLocal item = null;
        
        try{
            EJBHomeFactory factory = EJBHomeFactory.getInstance();
            ItemLocalHome home = (ItemLocalHome)factory.getLocalHome (EJBHomeFactory.ITEM);
            item = home.findByPrimaryKey(itemPK);
            return ((Integer) cart.get(item));
        }catch(Exception e){
            throw new javax.ejb.EJBException("Could not get the quantity for item"
                    + item , e);
        }
        
    }
    
    /**
     * 
     * Remove a specified number of items from the shopping cart
     * 
     * @param itemPK
     * @param quantity
     * 
     */
    
    private void removeItemFromCart(Integer itemPK, Integer quantity){
        ItemLocal item = null;
        try{
            EJBHomeFactory factory = EJBHomeFactory.getInstance();
            ItemLocalHome home = (ItemLocalHome)factory.getLocalHome (EJBHomeFactory.ITEM);
            item = home.findByPrimaryKey(itemPK);
            cart.remove(item);
            cart.put(item, quantity);
        }catch(Exception e){
            throw new javax.ejb.EJBException("Could not remove item "
                    + item , e);
        }
        
    }
    
    /**
     * Remove one item from the cart
     * 
     * @param itemPK
     * 
     * @ejb.interface-method
     * 
     */
    
    public void removeItemFromCart(Integer itemPK){
        ItemLocal item = null;
        try{
            EJBHomeFactory factory = EJBHomeFactory.getInstance();
            ItemLocalHome home = (ItemLocalHome)factory.getLocalHome (EJBHomeFactory.ITEM);
            item = home.findByPrimaryKey(itemPK);
            cart.remove(item);
        }catch(Exception e){
            throw new javax.ejb.EJBException("Could not remove item "
                    + item , e);
            
        }
    }
    
    /**
     * Update the quantity of an item in the cart
     * 
     * @param itemPK
     * @param quantity
     * 
     * @ejb.interface-method
     * 
     */
    
    public void updateQuantity(Integer itemPK, Integer quantity){
        ItemLocal item = null;
        if(quantity.intValue() <= 0){
            
            throw new NumberFormatException("Quantity must be greater than 0:");
        }
        
        try{
            EJBHomeFactory factory = EJBHomeFactory.getInstance();
            ItemLocalHome home = (ItemLocalHome)factory.getLocalHome (EJBHomeFactory.ITEM);
            item = home.findByPrimaryKey(itemPK);
            int orig = 0; Integer origInt;
            if((origInt = ((Integer) (cart.get(item))))!=null)   
                orig = ((Integer) (cart.get(item))).intValue();
            if(orig < quantity.intValue())
                addItemToCart(itemPK, quantity);
            else
                removeItemFromCart(itemPK, quantity);
            
            
        }catch(Exception e){
            throw new javax.ejb.EJBException("Could not update item "
                    + item , e);
            
        }
    }
    
    /**
     * Returns whether or not hte item is in the shopping cart
     * 
     * @param itemPK
     * @return whether or not the item is in the shopping cart
     * 
     * @ejb.interface-method
     * 
     */
    
    public boolean contains(Integer itemPK){
        ItemLocal item = null;
        try{
            EJBHomeFactory factory = EJBHomeFactory.getInstance();
            ItemLocalHome home = (ItemLocalHome)factory.getLocalHome (EJBHomeFactory.ITEM);
            item = home.findByPrimaryKey(itemPK);
            return cart.containsKey(item);
        }catch(Exception e){
            throw new javax.ejb.EJBException("Could not find item "
                    + itemPK , e);
        }
    }
    
    /**
     * Returns the total number of items in the cart
     * 
     * @return total number of items in the cart
     * 
     * @ejb.interface-method
     */
    
    public Integer listNumOfItems(){
        return new Integer(cart.size());
    }
    
    /**
     * Returns the total cost of items in the cart
     * 
     * @return total cost of items in the cart
     * 
     * @ejb.interface-method
     * 
     */
    
    public BigDecimal getTotalCost(){
        
        return recalculateTotal();
        
    }
    
    /**
     * Returns the items in the cart
     * 
     * @return the items in the cart
     * 
     * @ejb.interface-method
     * 
     */
    
    public Collection getItemsInCart(){
        return cart.keySet();
        
    }
    
    
    /**
     * Crate orders from the items in the cart
     *
     * @ejb.interface-method
     */
    
    public void createOrders(){
        ItemLocal item = null;
        String DATE_FORMAT = "yyyy-MM-dd";
        Date date = new Date();
        java.text.SimpleDateFormat sdf =
            new java.text.SimpleDateFormat(DATE_FORMAT);
        String strdate = sdf.format(date);
        
        try{
            Set items = cart.keySet();
            EJBHomeFactory factory = EJBHomeFactory.getInstance();
            OrderLocalHome orderHome = (OrderLocalHome)factory.getLocalHome (EJBHomeFactory.ORDER);
            Iterator it = items.iterator();
            
            Collection purchased = customer.getPurchased();
            while(it.hasNext())
            {
                item = ((ItemLocal) it.next());
                olstore.entity.OrderLocal order = orderHome.create(customer,
                        item, (Integer)(cart.get(item)), new String("Ordered"),
                        strdate, getCostForItem(item.getItemId()));
                if(!purchased.contains(item)){
                    purchased.add(item);
                }
            }
            
            customer.setPurchased(purchased);
            clearContents();
        }catch(Exception e){
            throw new javax.ejb.EJBException("Could not add item "
                    + item , e);
        }
    }
    
    private void clearContents(){
        cart.clear();
    }
    
    /**
     * @ejb.interface-method
     *
     */
    public ArrayList shoppingCartToDTOs(){
        Iterator itemIterator = getItemsInCart().iterator();
        ArrayList cartEntries = new ArrayList();
        while(itemIterator.hasNext()){
            ItemLocal currItemLocal = (ItemLocal)itemIterator.next();
            ShoppingCartItem cartItem = new ShoppingCartItem(currItemLocal);		
            cartItem.setQuantity(getQuantity(cartItem.getItemId()).toString());
            cartItem.setPrice(getCostForItem(cartItem.getItemId()));
            cartEntries.add(cartItem);
        }
        
        return cartEntries;
    }
    
    
    /**
     * Takes updated information from the form and transfers to the Shopping Cart.
     * @param cartEntries
     * 
     * @ejb.interface-method
     */
    public void DTOsToShoppingCart(ArrayList cartEntries){
        Iterator entriesIterator = cartEntries.iterator();
        while(entriesIterator.hasNext()){
            ShoppingCartItem cartItem = (ShoppingCartItem) entriesIterator.next();
            
            if(Integer.parseInt(cartItem.getQuantity())==0)
                removeItemFromCart(cartItem.getItemId());
            else
                updateQuantity(cartItem.getItemId(), new Integer(cartItem.getQuantity()));
        }
        
        recalculateTotal();
    }
    
    
    
    /**
     * @ejb.interface-method
     *
     */
    
    public BigDecimal getCostForItem(Integer itemPK){
        ItemLocal item = null;
        try{
            EJBHomeFactory factory = EJBHomeFactory.getInstance();
            ItemLocalHome home = (ItemLocalHome)factory.getLocalHome (EJBHomeFactory.ITEM);
            item = home.findByPrimaryKey(itemPK);
            return (item.getPrice().multiply(new BigDecimal(((Integer) cart.get(item)).toString())));
        }catch(Exception e){
            throw new javax.ejb.EJBException("Could not find item "
                    + itemPK , e);
        }
        
        
    }
    
    public void ejbRemove(){
    }
    
    public void ejbActivate(){
    }
    
    public void ejbPassivate(){	
    }
    
    public void setSessionContext(javax.ejb.SessionContext cntx){
		ejbContext = cntx;
		try{
			initialContext = new javax.naming.InitialContext();
		}catch(javax.naming.NamingException ne){
			throw new javax.ejb.EJBException(ne);
		}
	}
}
	
	
