/**
 * 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: Greg Lapouchnian
 *                     Patrick Smith
 *
 */

package olstore.domain.logic;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import olstore.domain.manager.CartManager;
import olstore.domain.manager.ItemManager;
import olstore.domain.manager.OrderManager;
import olstore.domain.manager.TypeManager;
import olstore.domain.manager.UserManager;
import olstore.dto.AddressValue;
import olstore.dto.ItemValue;
import olstore.dto.OrderEntry;
import olstore.dto.PictureValue;
import olstore.dto.TypeValue;
import olstore.dto.UserValue;
import olstore.entity.OrderLocal;
import olstore.session.ShoppingCartLocalHome;

/**
 * The implementation of the OlstoreFacade class, used for interacting
 * with the backend beans without directly referencing objects that can be replaced.
 * Actions are done through Manager classes which wrap the classes that can be removed and
 * replaced with new implementations.
 */
public class OlstoreImpl implements OlstoreFacade {

    // A wrapper that handles item related actions.
    private ItemManager item;

    // A wrapper that handles order related actions.
    private OrderManager order;

    // A wrapper that handles user related actions.
    private UserManager user;

    // A wrapper that handles cart related actions.
    private ShoppingCartLocalHome cart;

    // A wrapper that handles type related actions.
    private TypeManager type;

    // The default type for a new item.
    private String DEFAULT_TYPE;
    
	//-------------------------------------------------------------------------
	// Setter methods for dependency injection
	//-------------------------------------------------------------------------
    
    public void setItemManager(ItemManager item) {
        this.item = item;
    }
    
    public void setOrderManager(OrderManager order) {
        this.order = order;
    }
    
    public void setUserManager(UserManager user) {
        this.user = user;
    }
    
    public void setShoppingCart(ShoppingCartLocalHome cart) {
        this.cart = cart;
    }
    
    public void setTypeManager(TypeManager type) {
        this.type = type;
    }
    
    public void setDefaultType(String type) {
        DEFAULT_TYPE = type;
    }
    
	//-------------------------------------------------------------------------
	// Operation methods, implementing the OlstoreFacade interface
	//-------------------------------------------------------------------------

    /**
     * Returns an ItemValue that matches the given ID.
     * @param itemId the ID of the item to be returned.
     * @return an ItemValue for the item represted by the item ID.
     */
    public ItemValue getItemById(String itemId) throws Exception {
        return item.getItemById(itemId);
    }

    /**
     * Returns a PictureValue that matches the given item's ID.
     * @param itemId the ID for the item whose picture is to be returned.
     * @return a picture that belongs to the item given by itemId.
     */
    public PictureValue getPictureById(String itemId) throws Exception {
        return item.getPictureById(itemId);
    }

    /**
     * Returns all items in the database.
     * @return all items in the database as a Collection.
     */
    public Collection getAll() {
        return item.getAllItems();        
    }

    /**
     * Returns all items of the given type.
     * @param type the type of item being requested.
     * @return a collection of all items of the requested type.
     */
    public Collection getItemsByType(String type) {
        return item.getItemsByType(type);
    }

    /**
     * Returns a list of all types that are available.
     * @return a collection of all types that are available.
     */
    public Collection getTypes()  {
        try {
        return type.findAll();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Returns a cart manager for the given user.
     * @param username the username for the desired user's cart.
     * @return a cart manager object that can be used to interact with the user's shopping cart.
     */
    public CartManager getShoppingCart(String username) {
        return new CartManager(cart, user, username);
    }

    /**
     * Returns a collection of all orders placed by the user.
     * @param username the user whose orders we are returning.
     * @return a Collection of all orders by username.
     */
    public Collection getOrders(String username) {
        return user.getOrders(username);
    }

    /**
     * Returns the user value for username.
     * @param username the users name to return.
     * @return a UserValue representation of the user.
     */
    public UserValue getUser(String username) {
        return user.findUserValue(username);
    }

    /**
     * Returns all users in the database.
     * @return a Collection of all users in the database.
     */
    public Collection getAllUsers() {
        return user.findAll();
    }

    /**
     * Returns all items that have been purchased by the user.
     * @param username the name of the user.
     * @return a Collection of all items that have been purchased by the user.
     */
    public Collection getUserPurchased(String username) {
        return user.getUserPurchased(username);
    }

    /**
     * Finds all items that have been marked for the main page, and 
     * have been purchased by friends of the user.
     * @param username the user's name.
     * @return a collection of all items that have been marked for the main page,
     * and have been purchased by friends of the user.
     */
    public Collection findByMainPageAndFriendsOf(String username) {
        return item.findByMainPageAndFriendsOf(username);
    }

    /**
     * Finds all items that have been marked for the main page, and are on special.
     * @return a collection of all items that have been marked for the main page and are
     * on special.
     */
    public Collection findByMainPageAndSpecialOffer() {
        return item.findByMainPageAndSpecialOffer();
    }

    /**
     * Returns all items that have been marked for the main page.
     * @return a collection of all items that have been marked for the main page.
     */
    public Collection findByMainPage() {
        return item.findByMainPage();
    }

    /**
     * Saves the item given into the backend storage.
     * @param item the item to save.
     */
    public void saveItem(ItemValue item) throws Exception {
        this.item.saveItem(item);
    }

    /**
     * Saves the type given into the backend storage.
     * @param type the type to save.
     */
    public void saveType(TypeValue type) throws Exception {
        this.type.saveType(type);
    }

    /**
     * Saves the user given into backend storage.
     * @param user the user to save.
     * @param address the address of the user.
     * @param username the user's name.
     */
    public void saveUser(UserValue user, AddressValue address, String username) throws Exception {
        this.user.saveUser(user, address, username);
    }

    /**
     * Creates a new user with the given values and address.
     * @param user the user's information.
     * @param address the user's address information.
     */
    public void createUser(UserValue user, AddressValue address) throws Exception {
        this.user.createUser(user, address);
    }    

    /**
     * Returns the default type.
     * @return the default type.
     */
    public String getDefaultType() {
        return DEFAULT_TYPE;
    }

    /**
     * Returns a collection of properties for the given type.
     * @param type the type whose properties will be returned.
     * @return a collection of properties for the given type.
     */
    public Collection getPropertiesForType(String type) throws Exception {
        return this.item.getPropertiesForType(type);
    }

    /**
     * Returns if the database has been populated.
     * @return true if the database isn't empty of users, false otherwise.
     */
    public boolean isPopulated() {
        return !this.user.findAll().isEmpty();
    }

    /**
     * Returns a collection of all orders whose status can be updated.
     * @return collection of all orders whose status can be updated.
     */
    public Collection findOrdersForUpdate() {
        Collection orders = order.findOrdersForUpdate();
        Vector newOrders = new Vector();
        Iterator ordersIt = orders.iterator();
        while (ordersIt.hasNext()) {
            OrderEntry order = new OrderEntry((OrderLocal)ordersIt.next());
            newOrders.add(order);
        }
        return newOrders;
    }

    /**
     * Sets the status of the order given by ID with the given status.
     * @param id the ID of the order.
     * @param status the new status for the order.
     */
    public void setStatus(Integer id, String status) {
        order.setStatus(id, status);
    }
    
    
    /**
     * Record this item as interesting to the user.
     * 
     * @param itemId the ID of the item the user wants to mark as interesting
     * @param user the username of the currently logged in user
     * @throws Exception if there is an error making the change
     */
    public void markItemAsInteresting(Integer itemId, String user) throws Exception {
        item.markItemAsInteresting(itemId, user);
    }

    /**
     * Get a map of all the friends of the current user for each one of the items
     * in the collection.
     * 
     * @param username the currently logged in user
     * @param items the items that will be included in the friends map
     */
    public Map getFriendsMap(String username, Collection items) {
        Iterator i = items.iterator();
        Map m = new HashMap();
        while(i.hasNext()) {
            Integer itemId = ((ItemValue)i.next()).getItemId();
            Collection friends = user.findFriendsThatPurchasedItem(username, itemId);
            m.put(itemId, friends);
        }
        return m;
    }
}
    
