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;
	}
	
	public int getQuantity( int supplierId, int supplierProductId )
	{
		int q = 0;
		try
		{
			q = ( ( ShoppingCartProduct )( ( ( Hashtable )( products.get( new Integer( supplierId ) ) ) )
					.get( new Integer( supplierProductId ) ) ) ).getQuantity( );
		}
		catch( Exception e )
		{
			q = 0;
		}
		
		return q;
	}

	/**
	 * 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, Hashtable payments )
	{
		System.out.println( "EL CARRITO VA A CREAR LAS ORDENES" );
		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 "Enviado"
			order.setOrderStatus( 3 );
			//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 );

			float base = 0;
			float tax = 0;
			float total = 0;
			float discount = 0;

			// aca se busca el tipo de pago seleccionado para este proveedor
			String payMet = ( String )payments.get( supplierId + "" );
			PaymentMethod paymentMethod = new PaymentMethod( Integer.parseInt( payMet ) );

			// 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.setName( tempCartProduct.getName() );
				tempOrderProduct.setSupplierId( tempCartProduct.getSupplierId( ) );
				tempOrderProduct.setCode( tempCartProduct.getCode( ) );
				tempOrderProduct.setQuantity( tempCartProduct.getQuantity( ) );
				tempOrderProduct.setOrderId( order.getId( ) );
				tempOrderProduct.setOrderPrice( tempCartProduct.getPrice( ) );
                                    
				float with_tax = 0;
				float without_tax = 0;
				float tax_val = 0;
				float tax_por = ( float )tempCartProduct.getTax( );

				with_tax = ( float )tempCartProduct.getPrice( ) * tempCartProduct.getQuantity( );
				without_tax = with_tax / ( 1 + tax_por / 100 );
				tax_val = with_tax - without_tax;
				float disc = ( without_tax * paymentMethod.getDiscount( ) / 100 );

				without_tax -= disc;
				tax_val = without_tax * ( tax_por / 100 );
				with_tax = without_tax + tax_val;

				if( tax_por > 0 )
				{
					base += without_tax;
					tax += tax_val;
				}

				total += with_tax;
				discount += disc;

				// añado este producto a la orden
				order.addProduct( tempOrderProduct );
			}
			// añado los demas datos a la orden
			order.setTaxBase( base );
			order.setTax( tax );
			order.setValue( total );
			order.setDiscount( discount );
			order.setPaymentMethod( paymentMethod );

			// 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;
	}

}