package com.fenalco.entities;

import java.sql.Date;
import java.util.Calendar;
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;

/*
 * Supplier.java
 *
 * Created on 13 de agosto de 2004, 10:32 
 */

/**
 * Esta clase representa la tabla proveedor de la base de datos y encapsula cada
 * una de las operaciones que sobre esta se puedan realizar : inserción,
 * actualización, eliminación, consulta
 * 
 * @author Mario Linares Vásquez
 */

public class Supplier
{
	/**
	 * id el proveedor
	 */
	private int supplierId;

	/**
	 * nombre del proveedor
	 */
	private String supplierName;

	/**
	 * costo minimo de la orden que puede solicitar un minorista sobre el
	 * proveedor
	 */
	private double minimunOrder;

	/**
	 * bandera que indica si el proveedor va a ser visible ne el nurit
	 */
	private int nurit;

	/**
	 * GLN de la empresa
	 */
	private String gln;

	/**
	 * Tipo de facturación que se aplica al proveedor
	 */
	private int billingType;

	/**
	 * Valor entero que indica si el proveedor puede ser comparado en el
	 * catalogo. 0:No comparar 1:Comparar
	 */
	private int catalogueStatus;
        
        /**
	 * Url de la imagen del proveedor
	 */
        private String imageUrl;

	/**
	 * Constructor por defecto de la clase
	 */
	public Supplier( )
	{

	}

	/**
	 * Constructor que recibe el id del proveedor en la base de datos. Se debe
	 * usar en el caso de actualizaciones, borrado y consulta. Este constructor
	 * llama a la función miembro <CODE>loadData</CODE> con el parámetro
	 * supplierId con el fin de cargar los datos propios de ese proveedor que
	 * residen en la base de datos. Al usar este constructor si se desea
	 * modificar el valor de algún campo se deben utilizar los métodos
	 * consultores (setter).
	 * 
	 * @param supplierId
	 *            int que representa el id del proveedor en la base de datos
	 */
	public Supplier( int supplierId)
	{
		loadData(supplierId);
	}

	/**
	 * Este método carga de la tabla proveedor de la base de datos todos los
	 * valores de los campos en los atributos de la clase, a través del método
	 * <CODE>query</CODE> de la clase <CODE>SQLUtilities</CODE>
	 * 
	 * @return boolean que representa el exito del proceso de carga de los datos
	 * @param supplierId
	 *            identificador del proveedor
	 */
	public boolean loadData( int supplierId )
	{
		boolean respuesta = false;
		this.supplierId = supplierId;
		String sql = "SELECT tipo_fact_id, prov_pedido_minimo, prov_nurit, prov_url_imagen, prov_comparar " +
				"FROM proveedor " +
                                "WHERE empr_id=" + supplierId + ";";

		try
		{
			Vector res = SQLUtilities.query(sql);
			Hashtable datos = (Hashtable) res.elementAt(0);

			minimunOrder = ((Double) datos.get("prov_pedido_minimo2"))
					.doubleValue();
			nurit = ((Integer) datos.get("prov_nurit")).intValue();
			billingType = ((Integer) datos.get("tipo_fact_id")).intValue();
                        imageUrl = (String)datos.get("prov_url_imagen");
			catalogueStatus = ((Integer) datos.get("prov_comparar")).intValue();

			// para obtener información de la tabla empresa.
			sql = "SELECT empr_nombre_comercial, empr_gln FROM empresa WHERE empr_id="
					+ supplierId + ";";
			res = SQLUtilities.query(sql);
			datos = (Hashtable) res.elementAt(0);

			supplierName = (String) datos.get("empr_nombre_comercial");
                        gln = (String) datos.get("empr_gln");

			respuesta = true;
		}
		catch (QueryException ex)
		{
			respuesta = false;
		}
		return respuesta;
	}

	/**
	 * Este método guarda los atributos del proveedor en la base de datos. Se
	 * debe usar solo cuando se ha creado una instancia con el constructor por
	 * omisión. Para almacenar los datos en la tabla proveedor debe construir
	 * una consulta SQL de tipo <B>insert </B> a través del método <CODE>query
	 * </CODE> de la clase <CODE>SQLUtilities</CODE>
	 * 
	 * @return boolean que representa el exito del proceso de inserción
	 */
	public boolean saveData( Transaction transaction )
	{
		String sql = "INSERT INTO proveedor (" + "empr_id, " + "tipo_fact_id, "
				+ "prov_pedido_minimo, " + "prov_nurit, "
				+ "prov_url_imagen, " + "prov_comparar " + ") VALUES(" + supplierId + ", "
				+ billingType + ", " + minimunOrder + ", " + nurit + ", "
				+ "\'" + imageUrl + "\', " + catalogueStatus + ");";
                //System.out.println("Save query--> "+sql);
		transaction.addSql(sql);
		return true;
	}

	/**
	 * Realiza una consulta SQL de tipo update con el fin de actualizar los
	 * campos del proveedor modificados a través de los métodos setter.Para
	 * actualizar los datos en la tabla proveedor debe construir una consulta
	 * SQL de tipo <B>update </B> a través del método <CODE>query</CODE> de la
	 * clase <CODE>SQLUtilities</CODE>
	 * 
	 * @return boolean que representa el exito del proceso de actualización
	 */
	public boolean update( Transaction transaction )
	{
		String sql = "UPDATE proveedor SET " + "tipo_fact_id=" + billingType
				+ ", " + "prov_pedido_minimo=" + minimunOrder + ", "
				+ "prov_nurit=" + nurit + ", " 
				+ "prov_url_imagen=\'"+ imageUrl + "\', " + "prov_comparar=" + catalogueStatus + " " + "WHERE empr_id="
				+ supplierId + ";";
                //System.out.println("Update query--> "+sql);
		transaction.addSql(sql);
		return true;
	}

	/**
	 * Realiza una consulta SQL de tipo delete con el fin de eliminar el
	 * proveedor de la base de datos cuando se creo la instancia con el
	 * constructor que recibe el id como parámetro.
	 * 
	 * @return boolean que representa el exito del proceso de boorado
	 */
	public boolean delete( Transaction transaction )
	{
		// primero tengo que borrar todos los que referencian al proveedor:
		// - comunidad
		// - cotizacion
		// - factura
		// - pedido
		// - producto proveedor
		// - minorista proveedor

		try
		{
			// comunidad
			String sql = "SELECT comu_id FROM comunidad WHERE empr_id="
					+ supplierId + ";";
			Vector res = SQLUtilities.query(sql);
			for( int i = 0; i < res.size(); i++ )
			{
				Hashtable datos = (Hashtable) res.elementAt(i);
				Community c = new Community();
				c.setId(((Integer) datos.get("comu_id")).intValue());
				c.delete(transaction);
			}

			//cotizacion
			sql = "SELECT coti_id FROM cotizacion WHERE empr_id=" + supplierId
					+ ";";
			res = SQLUtilities.query(sql);
			for( int i = 0; i < res.size(); i++ )
			{
				Hashtable datos = (Hashtable) res.elementAt(i);
				Quote q = new Quote();
				q.setId(((Integer) datos.get("coti_id")).intValue());
				q.delete(transaction);
			}

			//factura
			sql = "SELECT fact_id FROM factura WHERE empr_id=" + supplierId
					+ ";";
			res = SQLUtilities.query(sql);
			for( int i = 0; i < res.size(); i++ )
			{
				Hashtable datos = (Hashtable) res.elementAt(i);
				Bill b = new Bill();
				b.setId(((Integer) datos.get("fact_id")).intValue());
				b.delete(transaction);
			}

			//pedido
			sql = "SELECT pedi_id FROM pedido WHERE empr_id=" + supplierId
					+ ";";
			res = SQLUtilities.query(sql);
			for( int i = 0; i < res.size(); i++ )
			{
				Hashtable datos = (Hashtable) res.elementAt(i);
				Order o = new Order();
				o.setId(((Integer) datos.get("pedi_id")).intValue());
				o.delete(transaction);
			}

			/*
			 * //producto proveedor sql = "SELECT prod_prov_id FROM
			 * producto_proveedor WHERE empr_id=" + supplierId + ";"; res =
			 * SQLUtilities.query(sql); for( int i = 0; i < res.size(); i++ ) {
			 * Hashtable datos = ( Hashtable )res.elementAt( i );
			 * SupplierProduct sp = new SupplierProduct();
			 * sp.setSupplierProductId( ( ( Integer )datos.get( "fact_id" )
			 * ).intValue() ); sp.delete(transaction); }
			 */

			// minorista proveedor
			sql = "DELETE FROM minorista_proveedor WHERE pro_empr_id="
					+ supplierId + ";";
			transaction.addSql(sql);

			sql = "DELETE FROM proveedor WHERE empr_id=" + supplierId + ";";
			transaction.addSql(sql);
			return true;
		}
		catch (Exception e)
		{
			return false;
		}
	}

	/**
	 * Este método permite a un proveedor asignar a un minorista como cliente
	 * 
	 * @param supplierId
	 *            Identificador del proveedor
	 * @param shopKeeperId
	 *            Identificador del minorista
	 * @return Valor booleano que indica si la operación tuvo éxito o no.
	 */
	public boolean addClient( int shopKeeperId, Transaction t )
	{
                /*
		String sql = "INSERT INTO minorista_proveedor VALUES("
				+ this.hashCode() + "," + shopKeeperId + ","
				+ this.getSupplierId() + ",0,1);";
                 */
                String sql = "INSERT INTO minorista_proveedor " +
                              "VALUES("+shopKeeperId+","+this.getSupplierId()+",0,1);";
                
                System.out.println( "Relación Comercial: " + sql ); 
                
		t.addSql(sql);
                return true;
	}
        
        public int hashCode( )
	{
		return (new java.util.Date()).hashCode();
	}

	/**
	 * Este método permite eliminar a un minorista de la lista de clientes del
	 * proveedor
	 * 
	 * @param supplierId
	 *            Identificador del proveedor
	 * @param shopKeeperId
	 *            Identificador del minorista
	 * @return Valor booleano que indica si la operación tuvo éxito o no.
	 */
	public boolean removeClient( int shopKeeperId, Transaction t )
	{
		boolean response = true;
		Vector result = new Vector();
		Hashtable aux = new Hashtable();

		String sql = "DELETE FROM minorista_proveedor WHERE empr_id='"
				+ shopKeeperId + "' AND pro_empr_id='" + this.getSupplierId()
				+ "';";
		//Volar los establecimientos del minorista de las comunidades

		String clientStoresSql = "SELECT DISTINCT comunidad.comu_id, establecimiento.esta_id "
				+ "FROM comunidad,comunidad_establecimiento,establecimiento "
				+ "WHERE comunidad.empr_id="
				+ this.getSupplierId()
				+ " AND "
				+ "establecimiento.empr_id=" + shopKeeperId + ";";
                
                //System.out.println( "Client Stores:"+clientStoresSql );

		try
		{
			result = SQLUtilities.query(clientStoresSql);
			int communityId = 0;
			Community community = new Community();
			if( result.size() > 0 )
			{
				for( int i = 0; i < result.size(); i++ )
				{
					aux = (Hashtable) result.elementAt(i);
					int comKey = ((Integer) aux.get("comu_id")).intValue();
					int storeKey = ((Integer) aux.get("esta_id")).intValue();
					if( comKey != communityId )
					{
						communityId = comKey;
						community = new Community(comKey);
						community.removeStore(t, storeKey);
					}
					else
					{
						community.removeStore(t, storeKey);
					}
				}
			}
		}
		catch (QueryException qe)
		{
			response = false;
		}
                //System.out.println( "Remove client:"+sql );
		t.addSql(sql);

		return response;
	}

	/**
	 * Consultor para el atributo supplierId.
	 * 
	 * @return Valor del atributo supplierId.
	 */
	public int getSupplierId( )
	{
		return supplierId;
	}

	/**
	 * Modificador para el atributo supplierId.
	 * 
	 * @param supplierId
	 *            Nuevo valor para el atributo supplierId.
	 */
	public void setSupplierId( int supplierId )
	{
		this.supplierId = supplierId;
	}

	/**
	 * Consultor para el atributo supplierName.
	 * 
	 * @return Valor del atributo supplierName.
	 */
	public java.lang.String getSupplierName( )
	{
		return supplierName;
	}

	/**
	 * Modificador para el atributo supplierName.
	 * 
	 * @param supplierName
	 *            Nuevo valor para el atributo supplierName.
	 */
	public void setSupplierName( java.lang.String supplierName )
	{
		this.supplierName = supplierName;
	}

	/**
	 * Consultor para el atributo minimunOrder.
	 * 
	 * @return Valor del atributo minimunOrder.
	 */
	public double getMinimunOrder( )
	{
		return minimunOrder;
	}

	/**
	 * Modificador para el atributo minimunOrder.
	 * 
	 * @param minimunOrder
	 *            Nuevo valor para el atributo minimunOrder.
	 */
	public void setMinimunOrder( double minimunOrder )
	{
		this.minimunOrder = minimunOrder;
	}

	/**
	 * Consultor para el atributo nurit.
	 * 
	 * @return Valor del atributo nurit.
	 */
	public int getNurit( )
	{
		return nurit;
	}

	/**
	 * Modificador para el atributo nurit.
	 * 
	 * @param nurit
	 *            Nuevo valor para el atributo nurit.
	 */
	public void setNurit( int nurit )
	{
		this.nurit = nurit;
	}

	/**
	 * Consultor para el atributo gln.
	 * 
	 * @return Valor del atributo gln.
	 */
	public String getGln( )
	{
		return gln;
	}

	/**
	 * Modificador para el atributo gln.
	 * 
	 * @param gln
	 *            Nuevo valor para el atributo gln.
	 */
	public void setGln( String gln )
	{
		this.gln = gln;
	}

	/**
	 * Consultor para el atributo billingType.
	 * 
	 * @return Valor del atributo billingType.
	 */
	public int getbillingType( )
	{
		return billingType;
	}

	/**
	 * Modificador para el atributo billingType.
	 * 
	 * @param billingType
	 *            Nuevo valor para el atributo billingType.
	 */
	public void setbillingType( int billingType )
	{
		this.billingType = billingType;
	}
        
        public String getBillingTypeName(){
            
            String billingName = "";
            Vector result = new Vector();
            String sql = "SELECT tipo_fact_nombre " +
                         "FROM tipo_facturacion " +
                         "WHERE tipo_fact_id=" + this.getbillingType() + ";";
            
            try{
            
                result = SQLUtilities.query( sql );
                if( result.size() > 0 ){
                    Hashtable aux = (Hashtable)result.get(0);
                    billingName = aux.get( "tipo_fact_nombre" ).toString();
                }
                
            }catch( QueryException qe ){
                System.out.println( qe.getMessage() );
                billingName = "No disponible";
            }
            
            return billingName;
            
        }
        
        /**
         * Getter for property imageUrl.
         * @return Value of property imageUrl.
         */
        public java.lang.String getImageUrl() {
            return imageUrl;
        }
        
        /**
         * Setter for property imageUrl.
         * @param imageUrl New value of property imageUrl.
         */
        public void setImageUrl(java.lang.String imageUrl) {
            this.imageUrl = imageUrl;
        }

	/**
	 * Genera el cobro al proveedor de acuerdo con el tipo de facturación que le
	 * sea asignada.
	 * 
	 * @return booleano que indica si la facturación al proveedor fué exitosa
	 */
	public boolean makeBill( Transaction transaction, Date date )
	{

		double parameterValue = DataAccess
				.getBillingParameterValue(this.billingType);
		double totalValue = 0;

		switch (this.billingType)
		{
			case 1: //transacción
				Date startDate = new Date(0);
				Date endDate = new Date(0);

				startDate = date;
				endDate = Date.valueOf(date.toString());
				Calendar c = Calendar.getInstance();
				c.setTime(startDate);

				endDate.setDate(c.getActualMaximum(5));

				OrderList orderList = new OrderList(this.supplierId, -1,
						"Proveedor", startDate, endDate, 0, false);
				Vector orders = orderList.getOrders();
				Enumeration e = orders.elements();

				while( e.hasMoreElements() )
				{
					Order order = (Order) e.nextElement();
					totalValue += order.getValue();
				}

				totalValue *= parameterValue / 100;
				break;
			case 2: //establecimientos
				int stores = DataAccess.getNumberActivatedStores(supplierId,
						date);
				totalValue = stores * parameterValue;
				break;
		}

		//Sentencia para ingresar la nueva factura
		String sql = "INSERT INTO factura (fact_id, esta_fact_id, empr_id, fact_fecha, fact_valor) VALUES ("
				+ this.hashCode()
				+ ", 2, "
				+ supplierId
				+ ", \'"
				+ date
				+ "\', " + totalValue + ");";
		transaction.addSql(sql);

		return true;
	}

	public static void setExclusive( int supplierId, int shopKeeperId,
			int exclusive, Transaction transaction )
	{
		String sql = "UPDATE minorista_proveedor SET mino_prov_exclusivo="
				+ exclusive + " WHERE pro_empr_id=" + supplierId
				+ " AND empr_id=" + shopKeeperId + ";";

		transaction.addSql(sql);
	}

	public static String getName( int id )
	{
		String name = "";
		try
		{
			String sql = "SELECT empr_nombre_comercial FROM empresa WHERE empr_id="
					+ id + ";";
			Vector res = SQLUtilities.query(sql);
			Hashtable data = (Hashtable) res.elementAt(0);
			name = (String) data.get("empr_nombre_comercial");
		}
		catch (Exception e)
		{
			System.out.println("Error buscando el nombre del proveedor --> "
					+ e);
		}
		return name;
	}

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

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

	public static int getUserCount( int companyId )
	{
		int userCount = -1;
		String sqlUsers = "SELECT count(*) as usercount FROM usuario WHERE empr_id ="
				+ companyId + ";";
		try
		{
			Vector result = SQLUtilities.query(sqlUsers);
			if( result.size() > 0 )
			{
				Hashtable aux = (Hashtable) result.elementAt(0);
				Object auxResult = aux.get("usercount");
				userCount = new Integer(auxResult.toString()).intValue();
			}
		}
		catch (QueryException qe)
		{
			System.out.println("Query Error " + qe);
		}
		return userCount;
	}
        
        
        public static void main(String[] args){
            Supplier s = new Supplier(964388);
            Transaction t = new Transaction();
            System.out.println( s.getSupplierName() );
            
            s.setImageUrl("/hello/moto.jpg");
            s.update(t);
            System.out.println(t.execute());
            System.out.println( s.getImageUrl() );
            System.exit(-1);
        }
        
        
}