package com.fenalco.entities;

import java.sql.Date;
import java.util.Enumeration;
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;
import com.fenalco.utilities.mail.MailHandler;

/**
 * Representa una cotización
 */
public class Quote
{
	/**
	 * Identificador de la cotización
	 */
	private int id;

	/**
	 * Identificador del establecimiento que está solicitando la cotización
	 */
	private int storeId;

	/**
	 * Nombre del establecimiento que está solicitando la cotización
	 */
	private String storeName;

	/**
	 * Identificador del usuario que está solicitando la cotización
	 */
	private String userId;

	/**
	 * Identificador del proveedor al que se está solicitando la cotización
	 */
	private int supplierId;

	/**
	 * Nombre del proveedor al que se está solicitando la cotización
	 */
	private String supplierName;

	/**
	 * Fecha en que se solicita la cotización
	 */
	private Date quoteDate;

	/**
	 * Breve descripción que se anexa a la información enviada en la cotización
	 */
	private String description;

	/**
	 * Identificador del estado de la cotización
	 */
	private int statusId;

	/**
	 * Estado de la cotización en texto
	 */
	private String statusName;

	/**
	 * valor total de la cotización
	 */
	private double value;

	/**
	 * Productos que hacen parte de la cotización, este Hashtable está
	 * organizado de la siguiente forma: - key: id del objeto QuoteProduct -
	 * Value: Objeto QuoteProduct
	 */
	private Hashtable products;

	/**
	 * Constructor por omisión, crea la cotización vacia
	 */
	public Quote( )
	{
		this.products = new Hashtable();
		this.quoteDate = new Date(0, 0, 0);

		id = this.hashCode();
	}

	/**
	 * Constructor que recibe el id de la cotización y llama al método loaddata
	 * para que cargue la información necesaria de la base de datos
	 * 
	 * @param id
	 *            Identificador de la cotización para buscarla en la base de
	 *            datos
	 */
	public Quote( int id)
	{
		// TODO: implement
		products = new Hashtable();
		this.quoteDate = new Date(0, 0, 0);
		this.loadData(id);
	}

	/**
	 * Carga la información de la cotización de la base de datos a partir del
	 * identificador
	 * 
	 * @param id
	 *            Identificador de la cotización
	 * @return booleano que indica si se pudo cargar la información
	 *         correctamente o no
	 */
	public boolean loadData( int id )
	{
		// TODO: implement
		Vector result = new Vector();
		String sql = "SELECT coti_id, establecimiento.esta_id, estado_cotizacion.esta_coti_id, "
				+ "empresa.empr_id, coti_fecha, coti_descripcion, "
				+ "establecimiento.esta_nombre,empresa.empr_nombre_comercial,esta_coti_nombre "
				+ "FROM cotizacion,establecimiento,empresa,estado_cotizacion "
				+ "WHERE coti_id="
				+ id
				+ " "
				+ "AND cotizacion.esta_id=establecimiento.esta_id "
				+ "AND cotizacion.empr_id=empresa.empr_id "
				+ "AND cotizacion.esta_coti_id=estado_cotizacion.esta_coti_id;";

		try
		{
			result = SQLUtilities.query(sql);

			Hashtable quote = (Hashtable) result.elementAt(0);

			this.setId(((Integer) quote.get("coti_id")).intValue());
			this.setStoreId(((Integer) quote.get("esta_id")).intValue());
			this.setStatusId(((Integer) quote.get("esta_coti_id")).intValue());
			this.setSupplierId(((Integer) quote.get("empr_id")).intValue());

			/*
			 * StringTokenizer st = new
			 * StringTokenizer((String)quote.get("coti_fecha"));
			 * st.hasMoreTokens(); this.quoteDate.setYear(new
			 * Integer(st.nextToken()).intValue()); st.hasMoreTokens();
			 * this.quoteDate.setMonth(new Integer(st.nextToken()).intValue());
			 * st.hasMoreTokens(); this.quoteDate.setDate(new
			 * Integer(st.nextToken()).intValue());
			 */
			this.setQuoteDate((Date) quote.get("coti_fecha"));

			this.setDescription((String) quote.get("coti_descripcion"));

			this.setStoreName((String) quote.get("esta_nombre"));
			this.setSupplierName((String) quote.get("empr_nombre_comercial"));
			this.setStatusName((String) quote.get("esta_coti_nombre"));

			Vector results = new Vector();

			//System.out.println(this.id);
			//System.out.println(this.storeName);
			//System.out.println(this.supplierName);

			sql = "SELECT prod_coti_id " + "FROM producto_cotizacion "
					+ "WHERE coti_id=" + id + ";";

			//System.out.println("SQL QuoteProducts: "+sql);

			results = SQLUtilities.query(sql);
			for( int i = 0; i < results.size(); i++ )
			{
				Hashtable temp = new Hashtable();
				temp = (Hashtable) results.elementAt(i);
				Integer key = (Integer) temp.get("prod_coti_id");
				this.products.put(key, new QuoteProduct(key.intValue()));
			}

			this.calculateValue();
			//System.out.println(this.value);

		}
		catch (QueryException qe)
		{
			//System.out.println("Error al cargar la cotizacion (Quote): "+qe);
			return false;
		}

		return true;
	}

	/**
	 * Almacena la información de la cotización en la base de datos como un
	 * nuevo registro usando el método <CODE>addSql</CODE> de la transacción
	 * 
	 * @return booleano que indica si se pudo almacenar la información
	 *         correctamente o no
	 * @param transaction
	 *            la transacción que se está ejecutando
	 */
	public boolean saveData( Transaction transaction )
	{
		this.setId(this.hashCode() + storeId + supplierId);

		String sql = "INSERT INTO cotizacion VALUES(" + id + ","
				+ this.getStoreId() + "," + this.getStatusId() + ","
				+ this.getSupplierId() + ", \'" + quoteDate + "\', \'\');";

		//System.out.println( "Para la cotización: " + sql );

		transaction.addSql(sql);

		Enumeration e = this.products.elements();

		while( e.hasMoreElements() )
		{
			QuoteProduct temp = new QuoteProduct();
			temp = (QuoteProduct) e.nextElement();
			temp.setQuoteId(id);
			temp.saveData(transaction);
		}

		return true;
	}

	/**
	 * Elimina una cotización de la base de datos usando el método <CODE>addSql
	 * </CODE> de la transacción
	 * 
	 * @return booleano que indica si se pudo eliminar la cotización o no
	 * @param transaction
	 *            la transacción que se está ejecutando
	 */
	public boolean delete( Transaction transaction )
	{
		// TODO: implement
		Enumeration e = this.products.elements();

		while( e.hasMoreElements() )
		{
			QuoteProduct temp = new QuoteProduct();
			temp = (QuoteProduct) e.nextElement();
			temp.delete(transaction);
		}

		String sql = "DELETE FROM cotizacion WHERE coti_id=" + this.getId()
				+ ";";
		transaction.addSql(sql);

		return true;
	}

	/**
	 * Actualiza la información de una cotización usando el método <CODE>addSql
	 * </CODE> de la transacción
	 * 
	 * @param transaction
	 *            la transacción que se está ejecutando
	 * @return booleano que indica si se pudo actualizar la información o no
	 */
	public boolean update( Transaction transaction )
	{
		boolean response = true;
		Enumeration e = this.products.keys();

		String sqlDelete = "DELETE FROM producto_cotizacion WHERE coti_id="
				+ this.getId() + ";";
		//       System.out.println(sqlDelete);
		transaction.addSql(sqlDelete);

		while( e.hasMoreElements() )
		{
			((QuoteProduct) this.products.get(e.nextElement()))
					.saveData(transaction);
		}

		String sql = "UPDATE cotizacion SET esta_id=" + this.getStoreId()
				+ ",esta_coti_id=" + this.getStatusId() + ",empr_id="
				+ this.getSupplierId() + ",coti_descripcion=\'"
				+ this.getDescription() + "\' WHERE coti_id=" + this.getId()
				+ ";";

		transaction.addSql(sql);

		return response;
	}

	/**
	 * envia un correo al proveedor informandole de la cotización que se le está
	 * solicitando
	 * 
	 * @return booleano que indica si se pudo enviar el correo o no
	 */
	public boolean submit( )
	{
		String sql = "SELECT empr_email " + "FROM empresa " + "WHERE empr_id="
				+ this.getSupplierId() + ";";
		boolean send = false;
		try
		{
			Vector result = new Vector();
			result = SQLUtilities.query(sql);
			Hashtable temp = (Hashtable) result.elementAt(0);
			MailHandler mh = MailHandler.getInstance();
			send = mh.sendMail("", (String) temp.get("empr_email"), "", "");
		}
		catch (Exception e)
		{
			send = false;
		}

		return send;
	}

	/**
	 * Envia un correo al minorista que solicitó la cotización con la respuesta
	 * dada por el proveedor
	 * 
	 * @return booleano que indica si se pudo enviar el correo o no
	 */
	public boolean answer( Transaction transaction, String subject,
			String message )
	{
		// TODO: implement
		String sql = "SELECT empr_email " + "FROM empresa, establecimiento "
				+ "WHERE empresa.empr_id=establecimiento.empr_id "
				+ "AND esta_id=" + this.getStoreId() + ";";
		boolean send = false;

		try
		{
			Vector result = new Vector();
			result = SQLUtilities.query(sql);
			Hashtable temp = (Hashtable) result.elementAt(0);
			Company company = new Company(this.getSupplierId());
			MailHandler mh = MailHandler.getInstance();
			send = mh.sendMail(company.getCommercialName() + "<"
					+ company.getEmail() + ">",
					(String) temp.get("empr_email"), subject, message);
		}
		catch (Exception e)
		{
			send = false;
		}

		return send;
	}

	/**
	 * Getter for property id.
	 * 
	 * @return Value of property id.
	 */
	public int getId( )
	{
		return id;
	}

	/**
	 * Setter for property id.
	 * 
	 * @param id
	 *            New value of property id.
	 */
	public void setId( int id )
	{
		this.id = id;
	}

	/**
	 * Getter for property storeId.
	 * 
	 * @return Value of property storeId.
	 */
	public int getStoreId( )
	{
		return storeId;
	}

	/**
	 * Setter for property storeId.
	 * 
	 * @param storeId
	 *            New value of property storeId.
	 */
	public void setStoreId( int storeId )
	{
		this.storeId = storeId;
	}

	/**
	 * Getter for property storeName.
	 * 
	 * @return Value of property storeName.
	 */
	public String getStoreName( )
	{
		return storeName;
	}

	/**
	 * Setter for property storeName.
	 * 
	 * @param storeName
	 *            New value of property storeName.
	 */
	public void setStoreName( String storeName )
	{
		this.storeName = storeName;
	}

	/**
	 * Getter for property supplierId.
	 * 
	 * @return Value of property supplierId.
	 */
	public int getSupplierId( )
	{
		return supplierId;
	}

	/**
	 * Setter for property supplierId.
	 * 
	 * @param supplierId
	 *            New value of property supplierId.
	 */
	public void setSupplierId( int supplierId )
	{
		this.supplierId = supplierId;
	}

	/**
	 * Getter for property supplierName.
	 * 
	 * @return Value of property supplierName.
	 */
	public java.lang.String getSupplierName( )
	{
		return supplierName;
	}

	/**
	 * Setter for property supplierName.
	 * 
	 * @param supplierName
	 *            New value of property supplierName.
	 */
	public void setSupplierName( java.lang.String supplierName )
	{
		this.supplierName = supplierName;
	}

	/**
	 * Getter for property quoteDate.
	 * 
	 * @return Value of property quoteDate.
	 */
	public Date getQuoteDate( )
	{
		return quoteDate;
	}

	/**
	 * Setter for property quoteDate.
	 * 
	 * @param quoteDate
	 *            New value of property quoteDate.
	 */
	public void setQuoteDate( java.sql.Date quoteDate )
	{
		this.quoteDate = quoteDate;
	}

	/**
	 * Getter for property description.
	 * 
	 * @return Value of property description.
	 */
	public java.lang.String getDescription( )
	{
		return description;
	}

	/**
	 * Setter for property description.
	 * 
	 * @param description
	 *            New value of property description.
	 */
	public void setDescription( java.lang.String description )
	{
		this.description = description;
	}

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

	/**
	 * Setter for property products.
	 * 
	 * @param products
	 *            New value of property products.
	 */
	public void setProducts( Hashtable products )
	{
		this.products = products;
	}

	/**
	 * @return Returns the statusId.
	 */
	public int getStatusId( )
	{
		return statusId;
	}

	/**
	 * @param statusId
	 *            The statusId to set.
	 */
	public void setStatusId( int statusId )
	{
		this.statusId = statusId;
	}

	/**
	 * @return Returns the statusName.
	 */
	public String getStatusName( )
	{
		return statusName;
	}

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

	/**
	 * @return Returns the userId.
	 */
	public String getUserId( )
	{
		return userId;
	}

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

	public void calculateValue( )
	{
		double total = 0;
		Enumeration keys = this.getProducts().keys();
		for( int i = 0; i < this.getProducts().size(); i++ )
		{
			QuoteProduct product = (QuoteProduct) this.getProducts().get(
					keys.nextElement());
			total = total + (product.getQuotePrice() * product.getQuantity());
		}
		this.setValue(total);
	}

	/**
	 * Getter for property value.
	 * 
	 * @return Value of property value.
	 */
	public double getValue( )
	{
		return value;
	}

	/**
	 * Setter for property value.
	 * 
	 * @param value
	 *            New value of property value.
	 */
	public void setValue( double value )
	{
		this.value = value;
	}

	/**
	 * Este método agrega un objeto de tipo QuoteProduct al Hashtable la
	 * cotización
	 * 
	 * @param product
	 *            producto a ser agregado
	 */
	public void addProduct( QuoteProduct product )
	{
		if( products.get(new Integer(product.getTableId())) == null )
		{
			this.getProducts().put(new Integer(product.getTableId()), product);
		}
		else
		{
			product.setTableId(product.getTableId() + 1);
			addProduct(product);
		}
	}

	public int hashCode( )
	{
		return (new java.util.Date()).hashCode();
	}

}