package com.fenalco.entities;

import java.sql.Date;
import java.sql.Time;
import java.util.Enumeration;
import java.util.Hashtable;

import com.fenalco.utilities.database.Transaction;

/**
 * Almacena los productos que el usuario va metiendo al carrito de compras
 */
public class ShoppingCart
{
	/**
	 * Los productos que pertenecen al carrito de compras. Este Hashtable está
	 * construido de la siguiente forma: - el key es el id del proveedor - el
	 * value es un Hashtable construido de la siguiente forma: - el key es el id
	 * del producto_proveedor - el value es un objeto de tipo
	 * ShoppingCartproduct () de esta forma se mantienen separados los productos
	 * de cada proveedor
	 */
	public Hashtable products;

	/**
	 * Constructor por omisión, crea el carrito vacio
	 */
	public ShoppingCart( )
	{
		// TODO: implement
		products = new Hashtable();
	}

	/**
	 * Adiciona un nuevo producto al carrito
	 * 
	 * @param product
	 *            El producto que se va a adicionar al carrito
	 * @return booleano que indica si la operación se realizó exitosamente o no
	 */
	public boolean addProduct( ShoppingCartProduct product )
	{
		boolean b = false;
		boolean res = true;
		int supplierId = product.getSupplierId();

		Enumeration e = products.keys();

		while( e.hasMoreElements() )
		{
			if( ((Integer) e.nextElement()).intValue() == supplierId )
			{
				b = true;
				break;
			}
		}

		if( !b )
		{
			if( product.getQuantity() >= product.getMinimum() )
			{
				products.put(new Integer(supplierId), new Hashtable());
			}
			else
			{
				res = false;
				return res;
			}
		}
		ShoppingCartProduct oldProduct = (ShoppingCartProduct) ((Hashtable) (products
				.get(new Integer(supplierId)))).get(new Integer(product
				.getSupplierProductId()));
		ShoppingCartProduct newProduct = null;
		/// el producto no estaba en el carrito de compras
		if( oldProduct == null )
		{
			newProduct = product;
		}
		else
		{
			newProduct = product;
			newProduct.setQuantity(product.getQuantity()
					+ oldProduct.getQuantity());

		}
		if( newProduct.getQuantity() >= newProduct.getMinimum() )
		{
			((Hashtable) (products.get(new Integer(supplierId)))).put(
					new Integer(product.getSupplierProductId()), newProduct);
		}
		else
		{
			res = false;
		}

		return res;
	}

	/**
	 * elimina un producto del carrito de compras
	 * 
	 * @param productId
	 *            identificador del objeto ProductShoppingCart que se va a
	 *            eliminar
	 * @return booleano que indica si la operación se realizó exitosamente o no
	 */
	public boolean removeProduct( int supplierId, int supplierProductId )
	{
		// TODO: implement
		((Hashtable) (products.get(new Integer(supplierId))))
				.remove(new Integer(supplierProductId));

		return true;
	}

	/**
	 * Cambia la cantidad de un producto en el carrito de compras
	 * 
	 * @param productId
	 *            Identificador del Objeto ProductShoppingCart
	 * @param newQuantity
	 *            Nueva cantidad del producto
	 * @return booleano que indica si la operación se realizó exitosamente o no
	 */
	public boolean changeQuantity( int supplierId, int supplierProductId,
			int newQuantity )
	{
		if( newQuantity == 0 )
		{
			try
			{
				Hashtable supp = (Hashtable) (products.get(new Integer(
						supplierId)));
				supp.remove(new Integer(supplierProductId));
				if( supp.isEmpty() )
				{
					products.remove(new Integer(supplierId));
				}
			}
			catch (Exception e)
			{

			}
		}
		else
		{
			if( newQuantity >= ((ShoppingCartProduct) (((Hashtable) (products
					.get(new Integer(supplierId)))).get(new Integer(
					supplierProductId)))).getMinimum() )
			{
				((ShoppingCartProduct) (((Hashtable) (products.get(new Integer(
						supplierId)))).get(new Integer(supplierProductId))))
						.setQuantity(newQuantity);
			}
			else
			{
				return false;
			}
		}
		return true;
	}

	/**
	 * Guarda los productos contenidos en el carrito de compras como una lista
	 * 
	 * @param companyId
	 *            Identificador del minorista que crea la lista
	 * @param listName
	 *            El nombre con el que se va a guardar la lista
	 * @param transaction
	 *            la transacción que se está ejecutando
	 * @return booleano que indica si la operación se realizó exitosamente o no
	 */
	public boolean saveList( int companyId, String listName,
			Transaction transaction )
	{
		ShoppingList list = new ShoppingList();

		list.setCompanyId(companyId);
		list.setListName(listName);

		// obtengo los proveedores que están en el carrito de compra
		Enumeration e = this.products.elements();

		// aqui se van a almacenar los productos de cada proveedor sacados del
		// carrito
		Hashtable tempHash = new Hashtable();

		// aqui se van a guardar todos los productos para luego pasarselos a la
		// lista
		Hashtable temp = new Hashtable();

		int i = 0;

		// hago el ciclo para cada proveedor
		while( e.hasMoreElements() )
		{

			ShoppingCartProduct tempCartProduct;

			// saco los productos de este proveedor
			tempHash = (Hashtable) e.nextElement();

			Enumeration e2 = tempHash.elements();

			// hago el ciclo por cada producto del proveedor
			while( e2.hasMoreElements() )
			{
				tempCartProduct = (ShoppingCartProduct) e2.nextElement();

				// creo un producto para la lista
				ShoppingListProduct tempListProduct = new ShoppingListProduct();

				tempListProduct.setSupplierProductId(tempCartProduct
						.getSupplierProductId());
				tempListProduct.setQuantity(tempCartProduct.getQuantity());

				// adiciono el producto al hashtable temporal
				temp.put(new Integer(i++), tempListProduct);
				//               i=i+1;
			}
		}

		// adiciono el hashtable de productos a la lista de compras
		list.setProducts(temp);

		// le digo a la lista de compras que se guarde
		list.saveData(transaction);

		return true;
	}

	/**
	 * Crea un objeto de tipo <CODE>Quote</CODE> por cada uno de los
	 * proveedores que se encuentran en el carrito, le adiciona la información
	 * de los productos .
	 * 
	 * @param storeId
	 *            Identificador del establecimiento al cual debe llegar el
	 *            pedido
	 * @return un Hashtable: key -> id del proveedor a quien se dirije la
	 *         cotización, object -> Cotización
	 *  
	 */
	public Hashtable createQuotes( int storeId )
	{
		boolean b = true;
		// almaceno las llaves, es decir los id's de los proveedores
		Enumeration keys = this.products.keys();

		// creo las cotizaciones que se van a hacer
		Hashtable quotes = new Hashtable();

		// ciclo por cada proveedor
		while( keys.hasMoreElements() )
		{
			Integer key = (Integer) keys.nextElement();
			int supplierId = (key).intValue();

			// creo la cotización para este proveedor
			Quote quote = new Quote();

			/// almaceno la información que debe ir en la cotización
			quote.setStoreId(storeId);
			quote.setSupplierId(supplierId);
			// el estado la cotización es "Enviada"
			quote.setStatusId(1);
			quote.setQuoteDate(new Date((new java.util.Date()).getTime()));

			// en e2 se almacenan los productos de la cotización
			Hashtable e2 = (Hashtable) products.get(key);

			// en e se almacenan las llaves de los productos de la cotización
			Enumeration e = e2.keys();

			// ciclo para cada producto dentro de la cotización
			while( e.hasMoreElements() )
			{
				// creo el objeto OrderProduct para cada producto de la
				// cotización
				QuoteProduct tempQuoteProduct = new QuoteProduct();

				// saco el siguiente producto del hashtable
				ShoppingCartProduct tempCartProduct = (ShoppingCartProduct) e2
						.get(e.nextElement());

				// almaceno la información necesaria en el QuoteProduct
				tempQuoteProduct.setSupplierProductId(tempCartProduct
						.getSupplierProductId());
				tempQuoteProduct.setSupplierId(tempCartProduct.getSupplierId());
				tempQuoteProduct.setCode(tempCartProduct.getCode());
				tempQuoteProduct.setQuantity(tempCartProduct.getQuantity());
				tempQuoteProduct.setQuoteId(quote.getId());
				tempQuoteProduct.setQuotePrice(0.0);

				// añado este producto a la cotización
				quote.addProduct(tempQuoteProduct);

			}

			// añado al hashtable de ordenes esta cotización
			quotes.put(new Integer(supplierId), quote);
		}

		// retorno todas las ordenes de todos los proveedores
		return quotes;
	}

	/**
	 * Crea un objeto de tipo <CODE>Order</CODE> por cada uno de los
	 * proveedores que se encuentran en el carrito, le adiciona la información
	 * de los productos . Antes de adicionar los productos al pedido, se
	 * verifica que ese proveedor llegue al establecimiento indicado, de lo
	 * contrario no se puede crear el pedido.
	 * 
	 * @param user
	 *            el usuario que está realizando la transacción, este representa
	 *            a la empresa que hace el pedido
	 * @param storeId
	 *            Identificador del establecimiento al cual debe llegar el
	 *            pedido
	 * @return un Hashtable: key -> id del proveedor a quien se dirije la orden,
	 *         object -> Orden
	 *  
	 */
	public Hashtable createOrders( int storeId )
	{
		boolean b = true;
		// almaceno las llaves, es decir los id's de los proveedores
		Enumeration keys = this.products.keys();

		// creo las ordenes que se van a hacer
		Hashtable orders = new Hashtable();

		// ciclo por cada proveedor
		while( keys.hasMoreElements() )
		{
			Integer key = (Integer) keys.nextElement();
			int supplierId = (key).intValue();

			// creo la orden para este proveedor
			Order order = new Order();

			/// almaceno la información que debe ir en el pedido
			order.setStoreId(storeId);
                        order.setStoreName(new Store(storeId).getName());
			order.setCompanyId(supplierId);
			order.setCompanyName((new Supplier(supplierId)).getSupplierName());
			// el estado del pedido es "Solicitado"
			order.setOrderStatus(1);
			//la orden se solicitó desde internet
			order.setOrderOriginId(1);
			order.setDate(new Date((new java.util.Date()).getTime()));
			order.setTime(new Time((new java.util.Date()).getTime()));
			order.setDevice(1);

			// en e2 se almacenan los productos del pedido
			Hashtable e2 = (Hashtable) products.get(key);

			// en e se almacenan las llaves de los productos del pedido
			Enumeration e = e2.keys();

			// ciclo para cada producto dentro del pedido
			while( e.hasMoreElements() )
			{
				// creo el objeto OrderProduct para cada producto del pedido
				OrderProduct tempOrderProduct = new OrderProduct();

				// saco el siguiente producto del hashtable
				ShoppingCartProduct tempCartProduct = (ShoppingCartProduct) e2
						.get(e.nextElement());

				// almaceno la información necesaria en el OrderProduct
				tempOrderProduct.setSupplierProductId(tempCartProduct
						.getSupplierProductId());
				tempOrderProduct.setSupplierId(tempCartProduct.getSupplierId());
				tempOrderProduct.setCode(tempCartProduct.getCode());
				tempOrderProduct.setQuantity(tempCartProduct.getQuantity());
				tempOrderProduct.setOrderId(order.getId());
				tempOrderProduct.setOrderPrice(tempCartProduct.getPrice());

				// añado este producto a la orden
				order.addProduct(tempOrderProduct);

			}

			// añado al hashtable de ordenes esta orden
			orders.put(new Integer(supplierId), order);
		}

		// retorno todas las ordenes de todos los proveedores
		return orders;
	}

	/**
	 * Getter para el atributo products.
	 * 
	 * @return Value of property products.
	 */
	public Hashtable getProducts( )
	{
		return products;
	}

	/**
	 * Setter para el atributo products.
	 * 
	 * @param products
	 *            Nuevo valor para el atributo products
	 */
	public void setProducts( Hashtable products )
	{
		this.products = products;
	}

	public int containsProduct( int prodId )
	{
		int quantity = 0;

		Enumeration e = products.elements();
		outer: while( e.hasMoreElements() )
		{
			Hashtable t = (Hashtable) e.nextElement(); // productos de cada
													   // proveedor
			Enumeration e1 = t.elements();
			while( e1.hasMoreElements() )
			{
				ShoppingCartProduct p = (ShoppingCartProduct) e1.nextElement();
				if( p.getSupplierProductId() == prodId )
				{
					quantity = p.getQuantity();
					break outer;
				}
			}
		}
		return quantity;
	}

	/**
	 * Retorna el valor total de los productos que se encuentran en el carrito
	 * de compras
	 */
	public double getTotalPrice( )
	{
		double price = 0;
		try
		{
			Enumeration e = products.elements();
			while( e.hasMoreElements() )
			{
				Hashtable prods = (Hashtable) e.nextElement();
				Enumeration e1 = prods.elements();
				while( e1.hasMoreElements() )
				{
					ShoppingCartProduct prod = (ShoppingCartProduct) e1
							.nextElement();
					price += (prod.getPrice() * prod.getQuantity());
				}
			}
		}
		catch (Exception e)
		{
			price = 0;
		}
		return price;
	}

}