package com.fenalco.entities;

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

import com.fenalco.utilities.database.QueryException; 
import com.fenalco.utilities.database.SQLUtilities;
import com.fenalco.utilities.database.Transaction;



/**
 * Representa una superoferta
 * 
 * @author Mario Linares Vásquez
 */
public class SuperOffer
{
	/**
	 * Identificador de la superoferta
	 */
	private int id;

	/**
	 * Identificador del producto que compone la superoferta
	 * (producto-proveedor)
	 */
	private int productId;

	/**
	 * Nombre del producto que compone la superoferta
	 */
	private String productName;

	/**
	 * Fecha en la cual se inicia la superoferta
	 */
	private Date startDate;

	/**
	 * fecha en la cual termina la superoferta
	 */
	private Date endDate;

	/**
	 * Descripción de la superoferta
	 */
	private String description;

	/**
	 * URL de la imagen de la superoferta (banner)
	 */
	private String imageUrl = "";

	/**
	 * Identificador del proveedor que publica la superoferta
	 */
	private int supplierId;

	/**
	 * Nombre del proveedor que publica la superoferta
	 */
	private String supplierName;

	/**
	 * Precio de la superoferta
	 */
	private double price;

	/**
	 * Número de existencias de la superoferta
	 */
	private int stock;
        
        
        /**
         *Código de barras (sólo lectura)
         */
        private String barCode;
        
        
        /**
         *Marca (solo lectura)
         */
        private String brand ;
        
        /**
         *Categoría (solo lectura)
         */
        
        private String category;
        
        /**
	 * Constructor por omisión, crea una superoferta vacia
	 */
	public SuperOffer( )
	{
		// TODO: implement
		startDate = new Date(0);
		endDate = new Date(0);
	}

	/**
	 * Constructor que recibe el id de la superoferta y llama al método loadData
	 * para que cargue la información desde loa base de datos
	 * 
	 * @param supperOfferId
	 *            identificador de la superoferta
	 */
	public SuperOffer( int superOfferId)
	{
		startDate = new Date(0);
		endDate = new Date(0);
		this.loadData(superOfferId);
	}

	/**
	 * Carga los datos de la superoferta de la base de datos a partir del
	 * identificador
	 * 
	 * @param superOfferId
	 *            Identificador de la superoferta
	 * @return booleano que indica si se pudo cargar la información o no
	 */
	public boolean loadData( int superOfferId ) 
	{
		boolean flag = true;
		try
		{

			String query = new String("SELECT empr_id,supe_ofer_producto,supe_ofer_fecha_inicio,supe_ofer_fecha_fin,supe_ofer_descripcion,supe_ofer_url_imagen,supe_ofer_existencias"
						  + " FROM super_oferta"
						  + " WHERE supe_ofer_id="
						  + superOfferId + ";");
                        
                        //System.out.println( query );
                        
			Vector results = new Vector();
			Hashtable temp = new Hashtable();
			results = SQLUtilities.query(query);
			temp = (Hashtable) results.elementAt(0);

			this.setId(superOfferId);
			this.setSupplierId( ((Integer) temp.get("empr_id")).intValue() );
			this.setProductId( ((Integer) temp.get("supe_ofer_producto")).intValue() );
			this.setDescription( (String) temp.get("supe_ofer_descripcion") );
			this.setImageUrl( (String) temp.get("supe_ofer_url_imagen") );
                        this.setStock( ((Integer) temp.get("supe_ofer_existencias")).intValue() );
                        //System.out.println(this.stock);
                        
                        
                        
			//fecha inicio
			String aux1 = ((Date) temp.get("supe_ofer_fecha_inicio")).toString();
			this.setStartDate(Date.valueOf(aux1));

			//fecha finalización
			String aux2 = ((Date) temp.get("supe_ofer_fecha_fin")).toString();
			this.setEndDate(Date.valueOf(aux2));

			//nombre del producto
			query = new String("SELECT prod_prov_descripcion_corta,prod_prov_marca,prod_prov_codigo,cate_prod_codigo"
					+ " FROM producto_proveedor" + " WHERE prod_prov_id="
					+ this.getProductId() + ";");
			results = new Vector();
			temp = new Hashtable();
			results = SQLUtilities.query(query);

			if( results.size() > 0 )
			{
				temp = (Hashtable) results.elementAt(0);
				this.setProductName((String) temp
						.get("prod_prov_descripcion_corta"));
                                this.setBrand((String) temp.get("prod_prov_marca"));
                                this.setBarCode((String) temp.get("prod_prov_codigo"));
                                int catCode = ((Integer) temp.get("cate_prod_codigo")).intValue();
                                this.setCategory(  new ProductCategory(catCode).getName() );
                                
                                
			}
			else
			{
				this.setProductName("No asignado");
			}

			//nombre del proveedor
			query = new String("SELECT empr_nombre_comercial" + " FROM empresa"
					+ " WHERE empr_id=" + this.getSupplierId() + ";");
			results = new Vector();
			temp = new Hashtable();
			results = SQLUtilities.query(query);

			if( results.size() > 0 )
			{
				temp = (Hashtable) results.elementAt(0);

				this
						.setSupplierName((String) temp
								.get("empr_nombre_comercial"));
			}

		}
		catch (QueryException qe)
		{
			System.out.println(qe.getMessage());
			flag = false;
		}

		return flag;
	}

	/**
	 * Almacena los datos de la superoferta en la base de datos como un nuevo
	 * registro creando el sql y adicionandolo a la transacción con el método
	 * <CODE>addSql</CODE>
	 * 
	 * @return booleano que indica si se pudo almacenar la información o no
	 * @param transaction
	 *            la transacción que se está ejecutando
	 */
	public boolean saveData( Transaction transaction )
	{
		boolean flag = true;
		this.imageUrl = "";
		this.setId( this.hashCode() );
		String query = new String("INSERT INTO super_oferta" + " VALUES ("
				+ this.getId() + "," + this.getSupplierId() + ","
				+ this.getProductId() + "," + "\'" + this.getStartDate()
				+ "\'," + "\'" + this.getEndDate() + "\'," + "\'"
				+ this.getDescription() + "\'," + "\'" + this.getImageUrl()
				+ "\', 0);");
		transaction.addSql(query);

		return flag;
	}

	/**
	 * Actualiza la información de la superoferta en la base de datos creando el
	 * sql y adicionandolo a la transacción con el método <CODE>addSql</CODE>
	 * 
	 * @return booleano que indica si se pudo actualizar la información o no
	 * @param transaction
	 *            la transacción que se está ejecutando
	 */
	public boolean update( Transaction transaction )
	{
		String query = new String("UPDATE super_oferta"
				+ " SET supe_ofer_producto=" + this.getProductId() + ","
				+ "supe_ofer_fecha_inicio=\'" + this.getStartDate() + "\',"
				+ "supe_ofer_fecha_fin=\'" + this.endDate + "\',"
				+ "supe_ofer_descripcion=\'" + this.getDescription() + "\',"
				+ "supe_ofer_url_imagen=\'" + this.getImageUrl() + "\',"
                                + "supe_ofer_existencias=" + this.getStock()
				+ " WHERE supe_ofer_id=" + this.getId() + ";");
                //System.out.println( query );
		transaction.addSql(query);
		return true;
	}

	/**
	 * Este método permite actualizar el producto asignado a una superoferta.
	 * 
	 * @param transaction
	 *            Transacción que se esta ejecutando
	 * @param productId
	 *            Identificador del producto
	 * @return Valor booleano que indica si la operación tuvo éxito o no
	 */
	public boolean updateProduc( Transaction transaction, int productId )
	{
		String sql = "UPDATE super_oferta SET supe_ofer_producto=" + productId
				+ " WHERE supe_ofer_id=" + this.getId() + ";";
		transaction.addSql(sql);
		return true;
	}
        
        /**
	 * Este método permite actualizar el valor de existencias de la superoferta.
	 * 
	 * @param transaction
	 *            Transacción que se esta ejecutando
	 *
	 * @return Valor booleano que indica si la operación tuvo éxito o no
	 */

        public boolean updateStock(Transaction transaction){
            String sql = "UPDATE super_oferta SET supe_ofer_existencias=" + this.getStock()
				+ " WHERE supe_ofer_id=" + this.getId() + ";";
            transaction.addSql(sql);
            return true;
            
        }
	/**
	 * Elimina la superoferta de la base de datos creando el sql y adicionandolo
	 * a la transacción con el método <CODE>addSql</CODE>
	 * 
	 * @return booleano que indica si se pudo eliminar la superoferta o no
	 * @param transaction
	 *            la transacción que se está ejecutando
	 */
	public boolean delete( Transaction transaction )
	{

		String query = new String("DELETE " + " FROM super_oferta"
				+ " WHERE supe_ofer_id=" + this.getId() + ";");
		transaction.addSql(query);

		return true;
	}

	/**
	 * Arma un pedido cuyo único producto es la superoferta y lo envia.
	 * 
	 * @param storeId
	 *            Identificador del establecimiento al cual va dirigido el
	 *            pedido
	 * @param quantity
	 *            cantidad que se va a comprar
	 * @return booleano que indica si se pudo enviar el pedido o no
	 */
	public boolean submit( int storeId, int communityId, int quantity,
			int orderOriginId, int device, int paymentId )
	{

		long time = (new java.util.Date()).getTime();
		PaymentMethod paymentMethod = new PaymentMethod(paymentId);
		Transaction transaction = new Transaction();
		PriceScale scale = new PriceScale(this.getProductId(), communityId);
                this.setStock(this.getStock()-quantity);
                this.updateStock(transaction);

		Order order = new Order();

		order.setStoreId(storeId);
                order.setStoreName(new Store(storeId).getName());
		order.setOrderStatus(1);
		order.setOrderOriginId(orderOriginId);
		//        System.out.println("el id del producto en sl
		// so-->"+this.getProductId());
		SupplierProduct sp = new SupplierProduct();
		sp.loadMinimalData(this.getProductId());

		order.setCompanyId(sp.getSupplierId());
		order.setDate(new Date(time));
		order.setTime(new Time(time));
		order.setDevice(device);
		order.setPaymentMethod(paymentMethod);

		OrderProduct product = new OrderProduct();
                product.setName(sp.getShortDescription());
                product.setCode(sp.getCode());
		product.setPrice(scale);

		product.setOrderId(order.getId());
		product.setQuantity(quantity);
		product.setOrderPrice(product.getPrice());
                product.setTax((double)sp.getTax());

		//        product.setPrice(supplierProduct.getPrice() );
		//TODO: toca sacar el precio de la comunidad
		product.setSupplierProductId(this.getProductId());

		order.addProduct(product);
		
                float iva = (float)(product.getTax()/100.0);
                float tax = (float)(iva);
                
                tax *= product.getPrice();
                tax *= quantity;
                order.setTax( tax );
                
                float base = (iva > 0) ? (float)(product.getPrice()*quantity)/(1+iva) : 0.0f;
                order.setTaxBase(base);
                order.setDiscount( (float)product.getPrice()*quantity * paymentMethod.getDiscount()/100);
                order.setValue(product.getPrice()*quantity);                
                order.setSuperOffer( id );
                order.setOrderStatus( 3 );
		order.saveData(transaction);
                order.submit();

		return (transaction.execute());
	}


	/**
	 * Getter para el atributo id.
	 * 
	 * @return valor del atributo id.
	 */
	public int getId( )
	{
		return id;
	}

	/**
	 * Setter para el atributo id.
	 * 
	 * @param id
	 *            nuevo valor del atributo id.
	 */
	public void setId( int id )
	{
		this.id = id;
	}

	/**
	 * Getter para el atributo productId.
	 * 
	 * @return valor del atributo productId.
	 */
	public int getProductId( )
	{
		return productId;
	}

	/**
	 * Setter para el atributo productId.
	 * 
	 * @param productId
	 *            nuevo valor del atributo productId.
	 */
	public void setProductId( int productId )
	{
		this.productId = productId;
	}

	/**
	 * Getter para el atributo productName.
	 * 
	 * @return valor del atributo productName.
	 */
	public java.lang.String getProductName( )
	{
		return productName;
	}

	/**
	 * Setter para el atributo productName.
	 * 
	 * @param productName
	 *            nuevo valor del atributo productName.
	 */
	public void setProductName( java.lang.String productName )
	{
		this.productName = productName;
	}

	/**
	 * Getter para el atributo startDate.
	 * 
	 * @return valor del atributo startDate.
	 */
	public java.sql.Date getStartDate( )
	{
		return startDate;
	}

	/**
	 * Setter para el atributo startDate.
	 * 
	 * @param startDate
	 *            nuevo valor del atributo startDate.
	 */
	public void setStartDate( java.sql.Date startDate )
	{
		this.startDate = startDate;
	}

	/**
	 * Getter para el atributo endDate.
	 * 
	 * @return valor del atributo endDate.
	 */
	public java.sql.Date getEndDate( )
	{
		return endDate;
	}

	/**
	 * Setter para el atributo endDate.
	 * 
	 * @param endDate
	 *            nuevo valor del atributo endDate.
	 */
	public void setEndDate( java.sql.Date endDate )
	{
		this.endDate = endDate;
	}

	/**
	 * Getter para el atributo description.
	 * 
	 * @return valor del atributo description.
	 */
	public java.lang.String getDescription( )
	{
		return description;
	}

	/**
	 * Setter para el atributo description.
	 * 
	 * @param description
	 *            nuevo valor del atributo description.
	 */
	public void setDescription( java.lang.String description )
	{
		this.description = description;
	}

	/**
	 * Getter para el atributo imageUrl.
	 * 
	 * @return valor del atributo imageUrl.
	 */
	public java.lang.String getImageUrl( )
	{
		return imageUrl;
	}

	/**
	 * Setter para el atributo imageUrl.
	 * 
	 * @param imageUrl
	 *            nuevo valor del atributo imageUrl.
	 */
	public void setImageUrl( java.lang.String imageUrl )
	{
		this.imageUrl = imageUrl;
	}

	/**
	 * @return Returns the supplierId.
	 */
	public int getSupplierId( )
	{
		return supplierId;
	}

	/**
	 * @param supplerId
	 *            The supplierId to set.
	 */
	public void setSupplierId( int supplierId )
	{
		this.supplierId = supplierId;
	}

	/**
	 * @return Returns the supplierName.
	 */
	public String getSupplierName( )
	{
		return supplierName;
	}

	/**
	 * @param supplierName
	 *            The supplierName to set.
	 */
	public void setSupplierName( String supplierName )
	{
		this.supplierName = supplierName;
	}

	public double getPrice( )
	{
		return this.price;
	}

        /**
         * Getter for property stock.
         * @return Value of property stock.
         */
        public int getStock() {
            return stock;
        }
        
        /**
         * Setter for property stock.
         * @param stock New value of property stock.
         */
        public void setStock(int stock) {
            this.stock = stock;
        }
        
        
	public void calculateValue( int communityId )
	{
		this.price = SupplierProduct.getPriceInCommunity(this.productId,
				communityId).doubleValue();

	}

        /**
         * Getter for property barCode.
         * @return Value of property barCode.
         */
        public java.lang.String getBarCode() {
            return barCode;
        }        
        
        /**
         * Setter for property barCode.
         * @param barCode New value of property barCode.
         */
        private void setBarCode(java.lang.String barCode) {
            this.barCode = barCode;
        }
        
        /**
         * Getter for property brand.
         * @return Value of property brand.
         */
        public java.lang.String getBrand() {
            return brand;
        }
        
        /**
         * Setter for property brand.
         * @param brand New value of property brand.
         */
        private void setBrand(java.lang.String brand) {
            this.brand = brand;
        }
        
        /**
         * Getter for property category.
         * @return Value of property category.
         */
        public java.lang.String getCategory() {
            return category;
        }
        
        /**
         * Setter for property category.
         * @param category New value of property category.
         */
        private void setCategory(java.lang.String category) {
            this.category = category;
        }
        
}